jack 3 months ago
parent
commit
9771fecd63
7 changed files with 83 additions and 42 deletions
  1. 1 3
      Dockerfile
  2. 8 9
      downloader.py
  3. 42 8
      main.py
  4. 1 0
      proxy.txt
  5. 5 6
      static/script.js
  6. 15 3
      static/style.css
  7. 11 13
      templates/index.html

+ 1 - 3
Dockerfile

@@ -1,12 +1,10 @@
-# 使用官方 Python 运行时作为基础镜像
 FROM python:3.11-slim
 
-# 设置工作目录
 WORKDIR /app
 
 COPY requirements.txt .
 
-RUN pip install --no-cache-dir -r requirements.txt
+RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn
 
 COPY . .
 

+ 8 - 9
downloader.py

@@ -8,17 +8,16 @@ class Downloader:
         self.output_dir = "downloads"
         os.makedirs(self.output_dir, exist_ok=True)
     
-    async def download(self, ip: str, port: str, url: str) -> str:
+    async def download(self, proxy_str: str, url: str) -> str:
         """
         下载文件的主要逻辑
-        这里你需要替换成你自己的下载逻辑
         """
         try:
-            # 这里是你原来的 Go 代码对应的 Python 逻辑
-            # 示例:使用代理下载文件
-            
-            # 构建代理
-            proxy = f"http://{ip}:{port}"
+            # 如果proxy_str不为空,构建代理配置
+            proxy = None
+            if proxy_str and ":" in proxy_str:
+                ip, port = proxy_str.split(":", 1)
+                proxy = f"http://{ip}:{port}"
             
             # 使用 httpx 异步下载
             async with httpx.AsyncClient(proxies=proxy, timeout=30.0) as client:
@@ -57,7 +56,7 @@ class Downloader:
         
         return filename or "downloaded_file"
     
-    async def download_image(self, ip: str, port: str, url: str) -> str:
+    async def download_image(self, proxy_str: str, url: str) -> str:
         """专门下载图片的方法"""
         # 这里可以添加图片下载的特殊逻辑
-        return await self.download(ip, port, url)
+        return await self.download(proxy_str, url)

+ 42 - 8
main.py

@@ -1,8 +1,7 @@
 from fastapi import FastAPI, Request
 from fastapi.staticfiles import StaticFiles
-from fastapi.responses import FileResponse
 from fastapi.templating import Jinja2Templates
-from fastapi.responses import JSONResponse
+from fastapi.responses import JSONResponse, FileResponse
 import uvicorn
 import glob
 import os
@@ -12,7 +11,7 @@ from utils import *
 
 app = FastAPI(title="EH-Downloader", version="1.0.0")
 
-# 在应用启动时检查并创建data文件夹和targets.txt
+# 在应用启动时检查并创建data文件夹和targets.txt,以及proxy.txt
 @app.on_event("startup")
 async def startup_event():
     # 检查并创建data文件夹
@@ -31,6 +30,15 @@ async def startup_event():
         print(f"创建文件: {targets_file}")
     else:
         print(f"文件已存在: {targets_file}")
+    
+    # 检查并创建proxy.txt文件
+    proxy_file = "proxy.txt"
+    if not os.path.exists(proxy_file):
+        with open(proxy_file, 'w', encoding='utf-8') as f:
+            f.write("127.0.0.1:7890\n")
+        print(f"创建文件: {proxy_file}")
+    else:
+        print(f"文件已存在: {proxy_file}")
 
 # 挂载静态文件和模板
 app.mount("/static", StaticFiles(directory="static"), name="static")
@@ -44,7 +52,24 @@ async def favicon():
 @app.get("/")
 async def home(request: Request):
     """主页面"""
-    return templates.TemplateResponse("index.html", {"request": request})
+    # 读取proxy.txt中的代理列表
+    proxies = []
+    try:
+        with open("proxy.txt", 'r', encoding='utf-8') as f:
+            proxies = [line.strip() for line in f.readlines() if line.strip()]
+    except Exception as e:
+        print(f"读取proxy.txt失败: {e}")
+        proxies = ["127.0.0.1:7890"]
+    
+    # 如果没有代理配置,使用默认值
+    if not proxies:
+        proxies = ["127.0.0.1:7890"]
+    
+    return templates.TemplateResponse("index.html", {
+        "request": request,
+        "proxies": proxies,
+        "default_proxy": proxies[0] if proxies else "127.0.0.1:7890"
+    })
 
 @app.post("/load_urls")
 async def load_urls():
@@ -89,18 +114,27 @@ async def clear_output():
     })
 
 class ProxyRequest(BaseModel):
-    ip: str
-    port: str
+    proxy: str  # 修改为单个proxy字段
 
 @app.post("/download_urls")
 async def download_urls(req: ProxyRequest):
-    proxy = f"http://{req.ip}:{req.port}"
+    # 解析proxy字符串为ip和port
+    if ":" in req.proxy:
+        ip, port = req.proxy.split(":", 1)
+        proxy = f"http://{ip}:{port}"
+    else:
+        proxy = None
     msg = await run_step1(proxy)
     return JSONResponse({"success": True, "message": msg})
 
 @app.post("/download_images")
 async def download_images(req: ProxyRequest):
-    proxy = f"http://{req.ip}:{req.port}"
+    # 解析proxy字符串为ip和port
+    if ":" in req.proxy:
+        ip, port = req.proxy.split(":", 1)
+        proxy = f"http://{ip}:{port}"
+    else:
+        proxy = None
     msg = await run_step2(proxy)
     return JSONResponse({"success": True, "message": msg})
 

+ 1 - 0
proxy.txt

@@ -0,0 +1 @@
+127.0.0.1:7890

+ 5 - 6
static/script.js

@@ -9,6 +9,7 @@ class DownloadTool {
         this.downloadImageBtn = document.getElementById('downloadImage');
         this.checkIncompleteBtn = document.getElementById('checkIncomplete');
         this.clearOutputBtn = document.getElementById('clearOutput');
+        this.proxySelect = document.getElementById('proxy');
         
         this.initEvents();
     }
@@ -84,28 +85,26 @@ class DownloadTool {
     }
     
     async downloadUrls() {
-        const ip = document.getElementById('ip').value;
-        const port = document.getElementById('port').value;
+        const proxy = this.proxySelect.value;
     
         this.showOutput('正在抓取画廊链接...', 'info');
         const res = await fetch('/download_urls', {
             method: 'POST',
             headers: { 'Content-Type': 'application/json' },
-            body: JSON.stringify({ ip, port })
+            body: JSON.stringify({ proxy })
         });
         const data = await res.json();
         this.showOutput(data.message, data.success ? 'success' : 'error');
     }
 
     async downloadImages() {
-        const ip = document.getElementById('ip').value;
-        const port = document.getElementById('port').value;
+        const proxy = this.proxySelect.value;
     
         this.showOutput('正在下载图片...', 'info');
         const res = await fetch('/download_images', {
             method: 'POST',
             headers: { 'Content-Type': 'application/json' },
-            body: JSON.stringify({ ip, port })
+            body: JSON.stringify({ proxy })
         });
         const data = await res.json();
         this.showOutput(data.message, data.success ? 'success' : 'error');

+ 15 - 3
static/style.css

@@ -39,7 +39,8 @@ label {
 }
 
 input[type="text"],
-input[type="url"] {
+input[type="url"],
+.proxy-select {
     width: 100%;
     padding: 12px;
     border: 2px solid #ddd;
@@ -49,7 +50,8 @@ input[type="url"] {
 }
 
 input[type="text"]:focus,
-input[type="url"]:focus {
+input[type="url"]:focus,
+.proxy-select:focus {
     outline: none;
     border-color: #667eea;
 }
@@ -202,4 +204,14 @@ input[type="url"]:focus {
 
 .form-row .form-group {
     flex: 1;
-}
+}
+
+/* 下拉框样式 */
+.proxy-select {
+    background-color: white;
+    cursor: pointer;
+}
+
+.proxy-select option {
+    padding: 8px;
+}

+ 11 - 13
templates/index.html

@@ -11,16 +11,13 @@
         <h1>EH</h1>
         
         <form id="downloadForm" class="form">
-            <div class="form-row">
-                <div class="form-group">
-                    <label for="ip">IP:</label>
-                    <input type="text" id="ip" name="ip" value="127.0.0.1" required>
-                </div>
-                
-                <div class="form-group">
-                    <label for="port">端口:</label>
-                    <input type="text" id="port" name="port" value="7890" required>
-                </div>
+            <div class="form-group">
+                <label for="proxy">代理设置:</label>
+                <select id="proxy" name="proxy" class="proxy-select" required>
+                    {% for proxy in proxies %}
+                    <option value="{{ proxy }}" {% if proxy == default_proxy %}selected{% endif %}>{{ proxy }}</option>
+                    {% endfor %}
+                </select>
             </div>
             
             <div class="form-group">
@@ -53,10 +50,10 @@
             <div class="usage-instructions">
                 <p><strong>工具使用步骤:</strong></p>
                 <ol>
-                    <li>设置代理IP和端口(如使用魔法工具)</li>
-                    <li>在<a href="https://e-hentai.org/" target="_blank">点解这里</a>获取需要下载的画廊URL</li>
+                    <li>从下拉框选择代理设置(代理配置保存在项目根目录的proxy.txt中)</li>
                     <li>将URL复制到项目目录下的data/targets.txt中, 一个画廊一个URL</li>
-                    <li><del>不要问问什么不直接填到页面, 我懒得写</del></li>
+                    <li>在<a href="https://e-hentai.org/" target="_blank">点解这里</a>获取需要下载的画廊URL</li>
+                    <li><del>不要问什么不直接填到页面, 我懒得写</del></li>
                     <li>点击"读取目标URL"加载 targets.txt 中的URL列表</li>
                     <li>点击"下载URL"开始抓取画廊链接</li>
                     <li>点击"下载图片"开始下载图片文件</li>
@@ -64,6 +61,7 @@
                     <li>使用"清理日志和JSON文件"清理临时文件</li>
                 </ol>
                 <p><strong>注意:</strong>请确保代理设置正确,且 targets.txt 文件中已添加目标URL。</p>
+                <p><strong>代理配置:</strong>在项目根目录的proxy.txt文件中,每行一个代理地址,格式为 IP:端口</p>
             </div>
         </div>
     </div>