jack 2 月之前
当前提交
71e6a827a3
共有 7 个文件被更改,包括 562 次插入0 次删除
  1. 二进制
      .DS_Store
  2. 194 0
      1step.py
  3. 182 0
      2step.py
  4. 64 0
      crawl.log
  5. 121 0
      download.log
  6. 二进制
      downloads/.DS_Store
  7. 1 0
      targets.txt

二进制
.DS_Store


+ 194 - 0
1step.py

@@ -0,0 +1,194 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+异步批量抓取 E-H 画廊图片链接,按专辑保存 json
+python eh_crawler.py
+"""
+from __future__ import annotations
+
+import asyncio
+import json
+import logging
+import re
+import sys
+from pathlib import Path
+from typing import Dict, List, Optional, Tuple
+
+import aiofiles
+import httpx
+from bs4 import BeautifulSoup
+from tqdm.asyncio import tqdm_asyncio
+from aiopath import AsyncPath
+
+# -------------------- 可配置常量 --------------------
+CONCURRENCY = 20                 # 并发页数
+MAX_PAGE = 100                   # 单专辑最大翻页
+RETRY_PER_PAGE = 5               # 单页重试
+TIMEOUT = httpx.Timeout(10.0)    # 请求超时
+PROXY = "http://127.0.0.1:7890"  # 科学上网代理,不需要留空
+IMG_SELECTOR = "#gdt"            # 图片入口区域
+FAILED_RECORD = "failed_keys.json"
+LOG_LEVEL = logging.INFO
+# ----------------------------------------------------
+
+logging.basicConfig(
+    level=LOG_LEVEL,
+    format="[%(asctime)s] [%(levelname)s] %(message)s",
+    handlers=[
+        logging.StreamHandler(sys.stdout),
+        logging.FileHandler("crawl.log", encoding="utf-8"),
+    ],
+)
+log = logging.getLogger("eh_crawler")
+
+# 预编译正则
+ILLEGAL_CHARS = re.compile(r'[<>:"/\\|?*\x00-\x1F]')
+
+
+# -------------------- 工具函数 --------------------
+def clean_folder_name(title: str) -> str:
+    """清洗文件夹名"""
+    return ILLEGAL_CHARS.sub("_", title).replace(" ", "").replace("_", "").strip() or "gallery"
+
+
+def load_targets() -> List[str]:
+    """读取 targets.txt"""
+    tgt = Path("targets.txt")
+    if not tgt.exists():
+        log.error("targets.txt 不存在,已自动创建,请先填写 URL")
+        tgt.touch()
+        sys.exit(0)
+    lines = [ln.strip() for ln in tgt.read_text(encoding="utf-8").splitlines() if ln.strip()]
+    if not lines:
+        log.error("targets.txt 为空,请先填写 URL")
+        sys.exit(0)
+    return list(set(lines))  # 去重
+
+
+def load_failed() -> List[str]:
+    if Path(FAILED_RECORD).exists():
+        try:
+            return json.loads(Path(FAILED_RECORD).read_text(encoding="utf-8"))
+        except Exception as exc:
+            log.warning(f"加载失败记录失败 -> {exc}")
+    return []
+
+
+def save_failed(keys: List[str]) -> None:
+    Path(FAILED_RECORD).write_text(json.dumps(keys, ensure_ascii=False, indent=2), encoding="utf-8")
+
+
+# -------------------- 爬虫核心 --------------------
+async def fetch_page(client: httpx.AsyncClient, url: str) -> Optional[str]:
+    """获取单页 HTML"""
+    for attempt in range(1, RETRY_PER_PAGE + 1):
+        try:
+            resp = await client.get(url)
+            resp.raise_for_status()
+            return resp.text
+        except httpx.HTTPError as exc:
+            log.error(f"[{attempt}/{RETRY_PER_PAGE}] 请求失败 {url} -> {exc}")
+            await asyncio.sleep(2 ** attempt)
+    return None
+
+
+async def crawl_single_gallery(
+    client: httpx.AsyncClient, sem: asyncio.Semaphore, gallery_url: str
+) -> bool:
+    """抓取单个画廊,成功返回 True"""
+    async with sem:
+        base_url = gallery_url.rstrip("/")
+        key = base_url.split("/")[-1]  # 用最后一截当 key
+        json_name = f"{key}.json"
+
+        folder_path: Optional[AsyncPath] = None
+        json_data: Dict[str, str] = {}
+        img_count = 1
+        last_page = False
+
+        for page in range(MAX_PAGE):
+            if last_page:
+                break
+            url = f"{base_url}?p={page}"
+            html = await fetch_page(client, url)
+            if html is None:
+                continue
+
+            soup = BeautifulSoup(html, "lxml")
+            title = soup.title.string if soup.title else "gallery"
+            clean_title = clean_folder_name(title)
+            folder_path = AsyncPath("downloads") / clean_title
+            await folder_path.mkdir(parents=True, exist_ok=True)
+
+            # 如果 json 已存在则跳过整个画廊
+            json_path = folder_path / json_name
+            if await json_path.exists():
+                log.info(f"{json_name} 已存在,跳过")
+                return True
+
+            log.info(f"当前页码:{page + 1}  {url}")
+
+            selected = soup.select_one(IMG_SELECTOR)
+            if not selected:
+                log.warning(f"未找到选择器 {IMG_SELECTOR}")
+                continue
+
+            links = re.findall(r'<a href="(.*?)"', selected.prettify())
+            if not links:
+                log.info("本页无图片入口,视为最后一页")
+                last_page = True
+                continue
+
+            for img_entry in links:
+                if img_entry in json_data.values():
+                    last_page = True
+                    break
+                json_data[f"{img_count:04d}"] = img_entry
+                img_count += 1
+
+        if json_data:
+            await json_path.write_text(
+                json.dumps(json_data, ensure_ascii=False, indent=2), encoding="utf-8"
+            )
+            log.info(f"保存成功 -> {json_path}  ({len(json_data)} 张)")
+            return True
+        else:
+            log.warning(f"{key} 未解析到任何图片链接")
+            return False
+
+
+# -------------------- 主流程 --------------------
+async def main() -> None:
+    targets = load_targets()
+    failed = load_failed()
+    if failed:
+        log.info(f"优先重试上次失败画廊: {len(failed)} 个")
+    all_urls = list(set(targets + failed))
+
+    proxy = PROXY if PROXY else None
+    limits = httpx.Limits(max_keepalive_connections=20, max_connections=50)
+    async with httpx.AsyncClient(
+        limits=limits, timeout=TIMEOUT, proxies=proxy, verify=True
+    ) as client:
+        sem = asyncio.Semaphore(CONCURRENCY)
+        results = await tqdm_asyncio.gather(
+            *[crawl_single_gallery(client, sem, u) for u in all_urls],
+            desc="Galleries",
+            total=len(all_urls),
+        )
+
+    # 失败持久化
+    new_failed = [u for u, ok in zip(all_urls, results) if not ok]
+    if new_failed:
+        save_failed(new_failed)
+        log.warning(f"本轮仍有 {len(new_failed)} 个画廊失败,已写入 {FAILED_RECORD}")
+    else:
+        Path(FAILED_RECORD).unlink(missing_ok=True)
+        log.info("全部画廊抓取完成!")
+
+
+if __name__ == "__main__":
+    try:
+        asyncio.run(main())
+    except KeyboardInterrupt:
+        log.info("用户中断,抓取结束")

+ 182 - 0
2step.py

@@ -0,0 +1,182 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+异步批量下载 EH 画廊真实图片
+python download_images.py
+"""
+from __future__ import annotations
+
+import asyncio
+import json
+import logging
+import re
+import sys
+from pathlib import Path
+from typing import Dict, List, Optional
+
+import aiofiles
+import httpx
+from aiopath import AsyncPath
+from tqdm.asyncio import tqdm_asyncio
+
+# -------------------- 可配置常量 --------------------
+CONCURRENCY = 20                 # 并发下载数
+RETRY_PER_IMG = 3                # 单图重试
+TIMEOUT = httpx.Timeout(15.0)    # 请求超时
+PROXY = "http://127.0.0.1:7890"  # 科学上网代理,不需要留空
+FAILED_RECORD = "failed_downloads.json"
+LOG_LEVEL = logging.INFO
+# ----------------------------------------------------
+
+logging.basicConfig(
+    level=LOG_LEVEL,
+    format="[%(asctime)s] [%(levelname)s] %(message)s",
+    handlers=[
+        logging.StreamHandler(sys.stdout),
+        logging.FileHandler("download.log", encoding="utf-8"),
+    ],
+)
+log = logging.getLogger("img_downloader")
+
+# 预编译正则
+IMG_URL_RE = re.compile(r'<img id="img" src="(.*?)"', re.S)
+EXT_RE = re.compile(r"\.(jpg|jpeg|png|gif|webp)$", re.I)
+
+
+# -------------------- 工具函数 --------------------
+def load_failed() -> List[Dict[str, str]]:
+    if Path(FAILED_RECORD).exists():
+        try:
+            return json.loads(Path(FAILED_RECORD).read_text(encoding="utf-8"))
+        except Exception as exc:
+            log.warning(f"加载失败记录失败 -> {exc}")
+    return []
+
+
+def save_failed(failed: List[Dict[str, str]]) -> None:
+    Path(FAILED_RECORD).write_text(json.dumps(failed, ensure_ascii=False, indent=2), encoding="utf-8")
+
+
+# -------------------- 下载核心 --------------------
+async def download_one(
+    client: httpx.AsyncClient, sem: asyncio.Semaphore, item: Dict[str, str]
+) -> bool:
+    """下载单张图,成功返回 True"""
+    img_path, img_url = Path(item["img_path"]), item["img_url"]
+
+    await sem.acquire()
+    try:
+        for attempt in range(1, RETRY_PER_IMG + 1):
+            try:
+                # 1. 获取详情页
+                resp = await client.get(img_url)
+                resp.raise_for_status()
+                real_url_match = IMG_URL_RE.search(resp.text)
+                if not real_url_match:
+                    log.warning(f"未解析到真实图片链接: {img_url}")
+                    return False          # <- 这里不会触发 await
+                real_url = real_url_match.group(1)
+
+                # 2. 下载真实图片(流式)
+                ext_match = EXT_RE.search(real_url)
+                ext = ext_match.group(1).lower() if ext_match else "jpg"
+                final_path = img_path.with_suffix(f".{ext}")
+
+                if await AsyncPath(final_path).exists():
+                    log.info(f"已存在,跳过: {final_path.name}")
+                    return True
+
+                async with client.stream("GET", real_url) as img_resp:
+                    img_resp.raise_for_status()
+                    await AsyncPath(final_path).parent.mkdir(parents=True, exist_ok=True)
+                    async with aiofiles.open(final_path, "wb") as fp:
+                        async for chunk in img_resp.aiter_bytes(chunk_size=65536):
+                            await fp.write(chunk)
+
+                log.info(f"[OK] {final_path.name}")
+                return True
+
+            except httpx.HTTPStatusError as exc:
+                if exc.response.status_code == 429:
+                    wait = 2 ** (attempt - 1)
+                    log.warning(f"[429] 等待 {wait}s 后重试({attempt}/{RETRY_PER_IMG})")
+                    await asyncio.sleep(wait)
+                else:
+                    log.error(f"[HTTP {exc.response.status_code}] {img_url}")
+                    break
+            except Exception as exc:
+                log.error(f"[ERROR] {img_url} -> {exc} ({attempt}/{RETRY_PER_IMG})")
+                await asyncio.sleep(1)
+
+        return False
+    finally:
+        sem.release()
+
+
+# -------------------- 扫描待下载列表 --------------------
+async def scan_tasks() -> List[Dict[str, str]]:
+    """扫描 downloads/ 下所有 json,返回待下载列表"""
+    result = []
+    root = AsyncPath("downloads")
+    if not await root.exists():
+        return result
+
+    async for json_path in root.rglob("*.json"):
+        folder = json_path.parent
+        try:
+            data: Dict[str, str] = json.loads(await json_path.read_text(encoding="utf-8"))
+        except Exception as exc:
+            log.warning(f"读取 json 失败 {json_path} -> {exc}")
+            continue
+
+        for img_name, img_url in data.items():
+            img_path = folder / img_name  # 无后缀
+            # 异步判断任意后缀是否存在
+            exists = False
+            for ext in (".jpg", ".jpeg", ".png", ".gif", ".webp"):
+                if await img_path.with_suffix(ext).exists():
+                    exists = True
+                    break
+            if not exists:
+                result.append({"img_path": str(img_path), "img_url": img_url})
+
+    return result
+
+
+# -------------------- 主流程 --------------------
+async def main() -> None:
+    # 1. 优先重试上次失败
+    failed_tasks = load_failed()
+    if failed_tasks:
+        log.info(f"优先重试上次失败任务: {len(failed_tasks)} 张")
+
+    tasks = failed_tasks + await scan_tasks()
+    if not tasks:
+        log.info("没有需要下载的图片,收工!")
+        return
+
+    proxy = PROXY if PROXY else None
+    limits = httpx.Limits(max_keepalive_connections=20, max_connections=50)
+    async with httpx.AsyncClient(limits=limits, timeout=TIMEOUT, proxies=proxy, verify=True) as client:
+        sem = asyncio.Semaphore(CONCURRENCY)
+        results = await tqdm_asyncio.gather(
+            *[download_one(client, sem, t) for t in tasks],
+            desc="Downloading",
+            total=len(tasks),
+        )
+
+    # 统计 & 持久化新失败
+    failed_again = [t for t, ok in zip(tasks, results) if not ok]
+    if failed_again:
+        save_failed(failed_again)
+        log.warning(f"本轮仍有 {len(failed_again)} 张下载失败,已写入 {FAILED_RECORD}")
+    else:
+        Path(FAILED_RECORD).unlink(missing_ok=True)
+        log.info("全部下载完成!")
+
+
+if __name__ == "__main__":
+    try:
+        asyncio.run(main())
+    except KeyboardInterrupt:
+        log.info("用户中断,下载结束")

+ 64 - 0
crawl.log

@@ -0,0 +1,64 @@
+[2025-09-26 16:47:21,272] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=0 "HTTP/1.1 200 OK"
+[2025-09-26 16:47:36,647] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=0 "HTTP/1.1 200 OK"
+[2025-09-26 16:47:56,144] [ERROR] [1/5] 请求失败 https://e-hentai.org/g/3550066/47d6393550?p=0 -> All connection attempts failed
+[2025-09-26 16:47:58,634] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=0 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:27,339] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=0 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:27,365] [INFO] 当前页码:1  https://e-hentai.org/g/3550066/47d6393550?p=0
+[2025-09-26 16:48:27,631] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=1 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:27,662] [INFO] 当前页码:2  https://e-hentai.org/g/3550066/47d6393550?p=1
+[2025-09-26 16:48:27,942] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=2 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:27,964] [INFO] 当前页码:3  https://e-hentai.org/g/3550066/47d6393550?p=2
+[2025-09-26 16:48:28,243] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=3 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:28,270] [INFO] 当前页码:4  https://e-hentai.org/g/3550066/47d6393550?p=3
+[2025-09-26 16:48:28,546] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=4 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:28,572] [INFO] 当前页码:5  https://e-hentai.org/g/3550066/47d6393550?p=4
+[2025-09-26 16:48:28,786] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=5 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:28,809] [INFO] 当前页码:6  https://e-hentai.org/g/3550066/47d6393550?p=5
+[2025-09-26 16:48:29,034] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=6 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:29,055] [INFO] 当前页码:7  https://e-hentai.org/g/3550066/47d6393550?p=6
+[2025-09-26 16:48:29,280] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=7 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:29,302] [INFO] 当前页码:8  https://e-hentai.org/g/3550066/47d6393550?p=7
+[2025-09-26 16:48:29,519] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=8 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:29,539] [INFO] 当前页码:9  https://e-hentai.org/g/3550066/47d6393550?p=8
+[2025-09-26 16:48:29,753] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=9 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:29,773] [INFO] 当前页码:10  https://e-hentai.org/g/3550066/47d6393550?p=9
+[2025-09-26 16:48:29,998] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=10 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:30,020] [INFO] 当前页码:11  https://e-hentai.org/g/3550066/47d6393550?p=10
+[2025-09-26 16:48:30,244] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=11 "HTTP/1.1 200 OK"
+[2025-09-26 16:48:30,262] [INFO] 当前页码:12  https://e-hentai.org/g/3550066/47d6393550?p=11
+[2025-09-26 16:48:30,267] [INFO] 保存成功 -> downloads/[Pixiv]玲殿下(81002566)2025.09.23-E-HentaiGalleries/47d6393550.json  (203 张)
+[2025-09-26 16:48:30,269] [INFO] 全部画廊抓取完成!
+[2025-09-26 17:12:54,122] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=0 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:54,148] [INFO] 当前页码:1  https://e-hentai.org/g/3550066/47d6393550?p=0
+[2025-09-26 17:12:54,372] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=1 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:54,396] [INFO] 当前页码:2  https://e-hentai.org/g/3550066/47d6393550?p=1
+[2025-09-26 17:12:54,658] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=2 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:54,683] [INFO] 当前页码:3  https://e-hentai.org/g/3550066/47d6393550?p=2
+[2025-09-26 17:12:55,063] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=3 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:55,086] [INFO] 当前页码:4  https://e-hentai.org/g/3550066/47d6393550?p=3
+[2025-09-26 17:12:55,447] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=4 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:55,474] [INFO] 当前页码:5  https://e-hentai.org/g/3550066/47d6393550?p=4
+[2025-09-26 17:12:55,786] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=5 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:55,812] [INFO] 当前页码:6  https://e-hentai.org/g/3550066/47d6393550?p=5
+[2025-09-26 17:12:56,048] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=6 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:56,068] [INFO] 当前页码:7  https://e-hentai.org/g/3550066/47d6393550?p=6
+[2025-09-26 17:12:56,294] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=7 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:56,314] [INFO] 当前页码:8  https://e-hentai.org/g/3550066/47d6393550?p=7
+[2025-09-26 17:12:56,549] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=8 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:56,572] [INFO] 当前页码:9  https://e-hentai.org/g/3550066/47d6393550?p=8
+[2025-09-26 17:12:56,797] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=9 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:56,822] [INFO] 当前页码:10  https://e-hentai.org/g/3550066/47d6393550?p=9
+[2025-09-26 17:12:57,117] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=10 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:57,139] [INFO] 当前页码:11  https://e-hentai.org/g/3550066/47d6393550?p=10
+[2025-09-26 17:12:57,361] [INFO] HTTP Request: GET https://e-hentai.org/g/3550066/47d6393550?p=11 "HTTP/1.1 200 OK"
+[2025-09-26 17:12:57,382] [INFO] 当前页码:12  https://e-hentai.org/g/3550066/47d6393550?p=11
+[2025-09-26 17:12:57,386] [INFO] 保存成功 -> downloads/[Pixiv]玲殿下(81002566)2025.09.23-E-HentaiGalleries/47d6393550.json  (203 张)
+[2025-09-26 17:12:57,388] [INFO] 全部画廊抓取完成!
+[2025-10-21 09:48:05,324] [INFO] HTTP Request: GET https://e-hentai.org/g/3592369/44385b2a36?p=0 "HTTP/1.1 200 OK"
+[2025-10-21 09:48:05,341] [INFO] 当前页码:1  https://e-hentai.org/g/3592369/44385b2a36?p=0
+[2025-10-21 09:48:05,572] [INFO] HTTP Request: GET https://e-hentai.org/g/3592369/44385b2a36?p=1 "HTTP/1.1 200 OK"
+[2025-10-21 09:48:05,582] [INFO] 当前页码:2  https://e-hentai.org/g/3592369/44385b2a36?p=1
+[2025-10-21 09:48:05,816] [INFO] HTTP Request: GET https://e-hentai.org/g/3592369/44385b2a36?p=2 "HTTP/1.1 200 OK"
+[2025-10-21 09:48:05,827] [INFO] 当前页码:3  https://e-hentai.org/g/3592369/44385b2a36?p=2
+[2025-10-21 09:48:05,830] [INFO] 保存成功 -> downloads/[Zefrost]Lumine[GenshinImpact][AIGenerated]-E-HentaiGalleries/44385b2a36.json  (39 张)
+[2025-10-21 09:48:05,833] [INFO] 全部画廊抓取完成!

+ 121 - 0
download.log

@@ -0,0 +1,121 @@
+[2025-10-21 09:50:09,289] [INFO] HTTP Request: GET https://e-hentai.org/s/5dc7e7c9ca/3592369-37 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,300] [INFO] HTTP Request: GET https://e-hentai.org/s/a289ed6092/3592369-6 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,306] [INFO] HTTP Request: GET https://e-hentai.org/s/e77d30e253/3592369-20 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,309] [INFO] HTTP Request: GET https://e-hentai.org/s/e8d19e3ff5/3592369-28 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,309] [INFO] HTTP Request: GET https://e-hentai.org/s/6d6ab9db19/3592369-17 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,318] [INFO] HTTP Request: GET https://e-hentai.org/s/0ad0ad6468/3592369-9 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,322] [INFO] HTTP Request: GET https://e-hentai.org/s/f4f85d3a9d/3592369-38 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,325] [INFO] HTTP Request: GET https://e-hentai.org/s/5eb45055e4/3592369-16 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,326] [INFO] HTTP Request: GET https://e-hentai.org/s/1bf21226cf/3592369-36 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,329] [INFO] HTTP Request: GET https://e-hentai.org/s/1f73a1930b/3592369-8 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,331] [INFO] HTTP Request: GET https://e-hentai.org/s/c17713f0bc/3592369-19 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,336] [INFO] HTTP Request: GET https://e-hentai.org/s/e1a514611c/3592369-18 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,338] [INFO] HTTP Request: GET https://e-hentai.org/s/3c29efdabf/3592369-26 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,340] [INFO] HTTP Request: GET https://e-hentai.org/s/157ab9c71f/3592369-2 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,442] [INFO] HTTP Request: GET https://e-hentai.org/s/af0d7dcb70/3592369-3 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,443] [INFO] HTTP Request: GET https://e-hentai.org/s/1d48859dbf/3592369-39 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,444] [INFO] HTTP Request: GET https://e-hentai.org/s/610b4330d0/3592369-7 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,451] [INFO] HTTP Request: GET https://ootkwsb.kwiddigykmru.hath.network/h/491e4290680f99be50445daeb1195b719d07bfcd-231324-1280-1871-wbp/keystamp=1761012000-b6dfac47c9;fileindex=206915210;xres=1280/6.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,504] [INFO] HTTP Request: GET https://e-hentai.org/s/f40dd06b93/3592369-10 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,508] [INFO] HTTP Request: GET https://e-hentai.org/s/a7e73c3fa1/3592369-29 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,509] [INFO] HTTP Request: GET https://e-hentai.org/s/a0b40a2f83/3592369-27 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,544] [INFO] HTTP Request: GET https://rgwxucy.aiuzlmvqxtsv.hath.network:2333/h/2154b90a033e96861f84162043af0cb77a0f48e4-242530-1280-1871-wbp/keystamp=1761012000-5047d72bfd;fileindex=206915260;xres=1280/37.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,597] [INFO] HTTP Request: GET https://edkvjgk.vuxolcremfnq.hath.network/h/479c43d09cc7c2eed15c0cd69b64dfcd91d01eb2-218708-1280-1806-wbp/keystamp=1761012000-c2bb866bdf;fileindex=206915213;xres=1280/9.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,609] [INFO] HTTP Request: GET https://abqwlpg.aarxvsksgsgb.hath.network/h/2d37b57cd28036b69d395d9c717a9b19869b90a3-215060-1280-1871-wbp/keystamp=1761012000-5f129c151a;fileindex=206915223;xres=1280/19.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,628] [INFO] [OK] 0006.webp
+[2025-10-21 09:50:09,660] [INFO] HTTP Request: GET https://eofajpt.vmzdvwgmbbym.hath.network:10550/h/1a273190063f21c73d8c13595123bef358733377-221852-1280-1871-wbp/keystamp=1761012000-a9046e82fb;fileindex=206915224;xres=1280/20.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,707] [INFO] HTTP Request: GET https://souqynf.xwnmkbyawzlw.hath.network/h/32970dd6c082aeb78d664faeaa4a6d2d1257c61c-249830-1280-1871-wbp/keystamp=1761012000-0e26ffcb90;fileindex=206915264;xres=1280/38.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,730] [INFO] HTTP Request: GET https://lvwpmir.kvkgycutnwul.hath.network/h/f856bce9c53f86f508e0a7bd0bd787a901ac41bd-192884-1280-1871-wbp/keystamp=1761012000-2d1d5f9608;fileindex=206915222;xres=1280/18.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,739] [INFO] [OK] 0009.webp
+[2025-10-21 09:50:09,748] [INFO] [OK] 0037.webp
+[2025-10-21 09:50:09,759] [INFO] [OK] 0019.webp
+[2025-10-21 09:50:09,776] [INFO] HTTP Request: GET https://fjhhobt.crleptkdnaih.hath.network:9999/h/eca0d63cbef2ce4799a5fcb54fc27a363add6f8e-254418-1280-1871-wbp/keystamp=1761012000-e7491ad660;fileindex=206915206;xres=1280/2.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,781] [INFO] [OK] 0020.webp
+[2025-10-21 09:50:09,783] [INFO] HTTP Request: GET https://zdfyyze.xlnvhrtompao.hath.network:8472/h/f3b93d2eaf86644298998640c8c12f3a28ccf4df-220886-1280-1871-wbp/keystamp=1761012000-42f53f2658;fileindex=206915257;xres=1280/36.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,784] [INFO] HTTP Request: GET https://rgwxucy.aiuzlmvqxtsv.hath.network:2333/h/761c4a67a633cb78a53d48160bf091fc5e3389df-246580-1280-1871-wbp/keystamp=1761012000-846ba026cf;fileindex=206915233;xres=1280/29.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,800] [INFO] [OK] 0038.webp
+[2025-10-21 09:50:09,806] [INFO] HTTP Request: GET https://azpbfqg.xycyegvkityr.hath.network/h/c0b2f298de3b5664755fa6d15aaad77df7300ac9-250078-1280-1871-wbp/keystamp=1761012000-6bbbce8e1f;fileindex=206915266;xres=1280/39.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,808] [INFO] HTTP Request: GET https://zdfyyze.xlnvhrtompao.hath.network:8472/h/8a519096aa5aef773cf1221afdf63e3595974303-137712-1280-876-wbp/keystamp=1761012000-3f39084973;fileindex=206915232;xres=1280/28.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,877] [INFO] [OK] 0018.webp
+[2025-10-21 09:50:09,917] [INFO] HTTP Request: GET https://e-hentai.org/s/c3086cd37a/3592369-30 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,942] [INFO] HTTP Request: GET https://dtnasqs.kvkgycutnwul.hath.network/h/20c17a63376f2a5f9bad449d842b0b27bbaa0e57-209450-1280-1871-wbp/keystamp=1761012000-6b30f2619c;fileindex=206915212;xres=1280/8.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,949] [INFO] HTTP Request: GET https://tfduazx.wsttelgpaeyt.hath.network/h/0e075486fb14aeb39124063ea4dd6ec046a880d9-210868-1280-1871-wbp/keystamp=1761012000-b9e1d48fe1;fileindex=206915211;xres=1280/7.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,955] [INFO] [OK] 0002.webp
+[2025-10-21 09:50:09,967] [INFO] HTTP Request: GET https://guihapy.hbspagyqqtxb.hath.network:40890/h/1cd65af761b8a18f883848d111f0fed050bd33af-147364-1280-876-wbp/keystamp=1761012000-b112f8e9e6;fileindex=206915231;xres=1280/27.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:09,972] [INFO] HTTP Request: GET https://keqaltd.jguqrykeppde.hath.network/h/8f893bf3b714bc0490c55303cc8dd822e221c826-168160-1280-1871-wbp/keystamp=1761012000-552e344f8c;fileindex=206915207;xres=1280/3.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,006] [INFO] [OK] 0028.webp
+[2025-10-21 09:50:10,008] [INFO] [OK] 0036.webp
+[2025-10-21 09:50:10,013] [INFO] [OK] 0029.webp
+[2025-10-21 09:50:10,013] [INFO] [OK] 0039.webp
+[2025-10-21 09:50:10,073] [INFO] HTTP Request: GET https://e-hentai.org/s/978a8534fe/3592369-11 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,082] [INFO] HTTP Request: GET https://e-hentai.org/s/68c135402c/3592369-21 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,085] [INFO] HTTP Request: GET https://e-hentai.org/s/034d7dbbe9/3592369-1 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,089] [INFO] HTTP Request: GET https://e-hentai.org/s/b4d07cf983/3592369-31 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,107] [INFO] [OK] 0007.webp
+[2025-10-21 09:50:10,121] [INFO] HTTP Request: GET https://e-hentai.org/s/79edc10e97/3592369-12 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,124] [INFO] HTTP Request: GET https://bnmmlpg.deaiusnxncea.hath.network:1443/h/a97c0aa83fcd713cd992f43530c2579215f53cd7-239002-1280-1871-wbp/keystamp=1761012000-d880bc702d;fileindex=206915220;xres=1280/16.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,129] [INFO] [OK] 0027.webp
+[2025-10-21 09:50:10,130] [INFO] [OK] 0008.webp
+[2025-10-21 09:50:10,159] [INFO] HTTP Request: GET https://e-hentai.org/s/e58ace2a4e/3592369-22 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,162] [INFO] [OK] 0003.webp
+[2025-10-21 09:50:10,173] [INFO] HTTP Request: GET https://e-hentai.org/s/7ca92ebded/3592369-32 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,192] [INFO] HTTP Request: GET https://vrbufha.vmfgucyvqdnc.hath.network:54200/h/3aefc20ea425d02066eabb3cc1e50e5704af76ef-187914-1280-1711-wbp/keystamp=1761012000-a2d6a67f93;fileindex=206915221;xres=1280/17.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,340] [INFO] HTTP Request: GET https://e-hentai.org/s/812f2f038d/3592369-23 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,342] [INFO] HTTP Request: GET https://mpikyhe.aiuzlmvqxtsv.hath.network:2333/h/753164bc8dc4542e0c230f638b4386ca8619cbe2-297430-1280-1979-wbp/keystamp=1761012000-d82874661b;fileindex=206915225;xres=1280/21.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,343] [INFO] HTTP Request: GET https://e-hentai.org/s/074e08084e/3592369-33 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,344] [INFO] HTTP Request: GET https://e-hentai.org/s/9c2a986a28/3592369-14 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,357] [INFO] HTTP Request: GET https://ivvskci.fzrmljssagym.hath.network:8440/h/15c1d8922362585a3dbf144c8826939be4081874-142306-1280-876-wbp/keystamp=1761012000-f889d50289;fileindex=206915244;xres=1280/32.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,358] [INFO] HTTP Request: GET https://e-hentai.org/s/4d1b0f3229/3592369-13 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,361] [INFO] HTTP Request: GET https://e-hentai.org/s/8cc11eedf4/3592369-24 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,366] [INFO] [OK] 0016.webp
+[2025-10-21 09:50:10,395] [INFO] HTTP Request: GET https://bkfffat.gndccnejxjhr.hath.network:11000/h/6f1ad3290e12aca2721e58c081921f4d09e99e4a-135842-1280-818-wbp/keystamp=1761012000-6fcdb7b47a;fileindex=206915237;xres=1280/30.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,398] [INFO] HTTP Request: GET https://e-hentai.org/s/d076c1acce/3592369-5 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,407] [INFO] HTTP Request: GET https://gkapxvr.tkxtucyyuokp.hath.network:5589/h/257cefeaa4e419fb0ea973b04ee1ce115eb17433-143432-1280-876-wbp/keystamp=1761012000-e92f233cfc;fileindex=206915240;xres=1280/31.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,417] [INFO] HTTP Request: GET https://rszxnyz.zvpgrcysqbsg.hath.network:9487/h/bd610b3c48497bb478a1497204d160dc16d92002-210912-1280-1871-wbp/keystamp=1761012000-0175ca693c;fileindex=206915216;xres=1280/12.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,424] [INFO] HTTP Request: GET https://e-hentai.org/s/2a6dd97367/3592369-34 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,466] [INFO] [OK] 0032.webp
+[2025-10-21 09:50:10,466] [INFO] [OK] 0030.webp
+[2025-10-21 09:50:10,552] [INFO] [OK] 0017.webp
+[2025-10-21 09:50:10,581] [INFO] HTTP Request: GET https://uamvwcc.dnaecumvegal.hath.network/h/eca101db83cdb56102ad266fe733f2e4ff6d8127-231550-1280-1871-wbp/keystamp=1761012000-961d434035;fileindex=206915227;xres=1280/23.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,586] [INFO] HTTP Request: GET https://kkyodzg.zcemqwwmmmnm.hath.network:10443/h/f1141462591835e3f0690e76e44932a9808095fd-227984-1280-1871-wbp/keystamp=1761012000-40bbfb0967;fileindex=206915214;xres=1280/10.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,587] [INFO] [OK] 0021.webp
+[2025-10-21 09:50:10,594] [INFO] HTTP Request: GET https://oecbenb.nklfziorgpct.hath.network/h/285f142ab77ba95bd880dc8696befe80d1b4824c-178230-1280-1871-wbp/keystamp=1761012000-d77335899a;fileindex=206915209;xres=1280/5.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,596] [INFO] [OK] 0031.webp
+[2025-10-21 09:50:10,614] [INFO] HTTP Request: GET https://scetefj.vybkgxtakdgj.hath.network:53999/h/7098e0c0a6f9ee59a7b203acb4a70abecee6b56f-203292-1280-1871-wbp/keystamp=1761012000-1535eba479;fileindex=206915205;xres=1280/1.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,616] [INFO] HTTP Request: GET https://tbvldoq.iaenqdfkpngs.hath.network:37828/h/a82a2fd04e6bd61c53bc7e3e4ef562780145d80d-217098-1280-1871-wbp/keystamp=1761012000-4920ac50c7;fileindex=206915215;xres=1280/11.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,618] [INFO] HTTP Request: GET https://e-hentai.org/s/a371ec0c01/3592369-15 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,624] [INFO] HTTP Request: GET https://zkwstjw.fzrmljssagym.hath.network/h/d140ded4f67a8fd900662363e3d6ad3603c4f083-217186-1280-1871-wbp/keystamp=1761012000-2364d9ff32;fileindex=206915217;xres=1280/13.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,637] [INFO] [OK] 0012.webp
+[2025-10-21 09:50:10,695] [INFO] [OK] 0005.webp
+[2025-10-21 09:50:10,731] [INFO] [OK] 0023.webp
+[2025-10-21 09:50:10,736] [INFO] HTTP Request: GET https://nynqbxc.fqwheaagiqwm.hath.network/h/624290c99f27508b2b9d3e744c1c19f6e89fe5b2-214622-1280-1871-wbp/keystamp=1761012000-dc67546278;fileindex=206915218;xres=1280/14.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,740] [INFO] HTTP Request: GET https://nynqbxc.fqwheaagiqwm.hath.network/h/64940e0c9d9dcfbe44766f168b42de206f1bab2e-203374-1280-1871-wbp/keystamp=1761012000-4ce1461501;fileindex=206915247;xres=1280/33.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,747] [INFO] HTTP Request: GET https://tjelitm.wudbjgwegqea.hath.network:8002/h/15eee1dfb95499144b5fc68fd29441de14cbc811-241544-1280-1871-wbp/keystamp=1761012000-b38884a626;fileindex=206915226;xres=1280/22.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,790] [INFO] HTTP Request: GET https://e-hentai.org/s/18199002ef/3592369-25 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,792] [INFO] HTTP Request: GET https://e-hentai.org/s/e8f6dba369/3592369-35 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,821] [INFO] [OK] 0011.webp
+[2025-10-21 09:50:10,850] [INFO] [OK] 0001.webp
+[2025-10-21 09:50:10,854] [INFO] HTTP Request: GET https://pgymasw.nghujfsbvlwr.hath.network:1024/h/7830f171c2e6a6079c63d02a51808cbc20db0ef0-216106-1280-1871-wbp/keystamp=1761012000-5c4d4e2949;fileindex=206915228;xres=1280/24.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:10,866] [INFO] [OK] 0013.webp
+[2025-10-21 09:50:10,891] [INFO] [OK] 0022.webp
+[2025-10-21 09:50:10,892] [INFO] [OK] 0033.webp
+[2025-10-21 09:50:10,902] [INFO] [OK] 0014.webp
+[2025-10-21 09:50:10,909] [INFO] HTTP Request: GET https://xtrkjip.qialcjprjsjy.hath.network:32342/h/c94e5c3bc32877a80e789b17dc44a4de2c8c0e0b-204386-1280-1871-wbp/keystamp=1761012000-beef96ea24;fileindex=206915250;xres=1280/34.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:11,042] [INFO] [OK] 0024.webp
+[2025-10-21 09:50:11,087] [INFO] HTTP Request: GET https://zyzursa.xwnmkbyawzlw.hath.network/h/fdd055dc8b74984aa2aee5a761c6fbe4f284b9ad-246060-1280-1871-wbp/keystamp=1761012000-13f52032e1;fileindex=206915254;xres=1280/35.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:11,116] [INFO] HTTP Request: GET https://byravvz.aqhqjktsvooz.hath.network:10550/h/cc5b5c5d9f67270847048df1944d2fddc1f316c1-226938-1280-1871-wbp/keystamp=1761012000-855cbeeab0;fileindex=206915219;xres=1280/15.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:11,170] [INFO] HTTP Request: GET https://dpoonwl.vmfgucyvqdnc.hath.network:54200/h/190563367f45e65e9a265b89670e5a48c97b5d70-145580-1280-876-wbp/keystamp=1761012000-1a6d164095;fileindex=206915229;xres=1280/25.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:11,175] [INFO] [OK] 0010.webp
+[2025-10-21 09:50:11,178] [INFO] [OK] 0034.webp
+[2025-10-21 09:50:11,376] [INFO] [OK] 0035.webp
+[2025-10-21 09:50:11,378] [INFO] [OK] 0015.webp
+[2025-10-21 09:50:11,388] [INFO] [OK] 0025.webp
+[2025-10-21 09:50:15,028] [ERROR] [ERROR] https://e-hentai.org/s/b196df0720/3592369-4 ->  (1/3)
+[2025-10-21 09:50:16,319] [INFO] HTTP Request: GET https://e-hentai.org/s/b196df0720/3592369-4 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:17,525] [INFO] HTTP Request: GET https://ywfviwx.cjvambnkjwfw.hath.network/h/bee0622509a464a1227f66a781d88baa1ddf3cad-266006-1280-1871-wbp/keystamp=1761012000-29e47aca95;fileindex=206915230;xres=1280/26.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:18,149] [INFO] [OK] 0026.webp
+[2025-10-21 09:50:21,327] [ERROR] [ERROR] https://e-hentai.org/s/b196df0720/3592369-4 ->  (2/3)
+[2025-10-21 09:50:22,638] [INFO] HTTP Request: GET https://e-hentai.org/s/b196df0720/3592369-4 "HTTP/1.1 200 OK"
+[2025-10-21 09:50:23,355] [INFO] HTTP Request: GET https://rfnbhfn.bmipocmfowxa.hath.network/h/999ef03dd73f17fbe139e124d438e9880617bcdb-157866-1280-1871-wbp/keystamp=1761012000-114cdaa4d5;fileindex=206915208;xres=1280/4.webp "HTTP/1.1 200 OK"
+[2025-10-21 09:50:23,517] [INFO] [OK] 0004.webp
+[2025-10-21 09:50:23,518] [INFO] 全部下载完成!

二进制
downloads/.DS_Store


+ 1 - 0
targets.txt

@@ -0,0 +1 @@
+https://e-hentai.org/g/3592369/44385b2a36/