143 lines
6.4 KiB
HTML
143 lines
6.4 KiB
HTML
<!DOCTYPE html>
|
||||
|
|
<html lang="zh-CN">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>通用爬虫系统</title>
|
|||
|
|
<link rel="stylesheet" href="style.css">
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<header>
|
|||
|
|
<div class="logo">🕷️ 通用爬虫系统 <span id="version" class="version"></span></div>
|
|||
|
|
<div class="header-right">
|
|||
|
|
<span class="status-pill" id="statusPill">运行中任务: 0</span>
|
|||
|
|
<button id="btnRefresh" class="btn ghost">⟳ 刷新</button>
|
|||
|
|
<button id="btnNew" class="btn primary">+ 新建任务</button>
|
|||
|
|
</div>
|
|||
|
|
</header>
|
|||
|
|
|
|||
|
|
<main>
|
|||
|
|
<div id="taskList" class="task-grid"></div>
|
|||
|
|
<div id="emptyState" class="empty hidden">
|
|||
|
|
<div class="empty-icon">🕸️</div>
|
|||
|
|
<p>还没有爬取任务</p>
|
|||
|
|
<button id="btnNew2" class="btn primary">+ 创建第一个任务</button>
|
|||
|
|
</div>
|
|||
|
|
</main>
|
|||
|
|
|
|||
|
|
<!-- 新建 / 编辑任务弹窗 -->
|
|||
|
|
<div id="taskModal" class="modal-overlay hidden">
|
|||
|
|
<div class="modal">
|
|||
|
|
<div class="modal-head">
|
|||
|
|
<span id="modalTitle">新建爬取任务</span>
|
|||
|
|
<button class="btn ghost sm" data-close>✕</button>
|
|||
|
|
</div>
|
|||
|
|
<div class="tabs" id="modeTabs">
|
|||
|
|
<button class="tab active" data-mode="batch">📄 批量爬取</button>
|
|||
|
|
<button class="tab" data-mode="scheduled">⏰ 定时爬取</button>
|
|||
|
|
<button class="tab" data-mode="auto">🤖 自动爬取</button>
|
|||
|
|
</div>
|
|||
|
|
<form id="taskForm">
|
|||
|
|
<div class="form-body">
|
|||
|
|
<div class="field"><label>项目名称 *</label><input name="name" required placeholder="例如: TPU 评测抓取"></div>
|
|||
|
|
<div class="field"><label>输出目录</label><input name="out_dir" placeholder="留空自动: out/任务ID;可填绝对路径"></div>
|
|||
|
|
<div class="row2">
|
|||
|
|
<div class="field"><label>爬取间隔(秒) 最小</label><input name="delay_min" type="number" min="0.1" step="0.1" value="2"></div>
|
|||
|
|
<div class="field"><label>最大</label><input name="delay_max" type="number" min="0.1" step="0.1" value="5"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="row2">
|
|||
|
|
<div class="field"><label>单页超时(秒)</label><input name="timeout" type="number" value="60"></div>
|
|||
|
|
<div class="field"><label>失败重试次数</label><input name="retry_count" type="number" value="2"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="row2">
|
|||
|
|
<div class="field"><label>重试间隔(秒)</label><input name="retry_interval" type="number" value="3"></div>
|
|||
|
|
<div class="field check"><label><input name="crawl_images" type="checkbox"> 爬取图片</label></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="row2">
|
|||
|
|
<div class="field check"><label><input name="notify" type="checkbox"> 完成后邮件通知</label></div>
|
|||
|
|
<div class="field"><label>通知邮箱</label><input name="notify_email" value="wlq@tphai.com"></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="field" id="urlsField"><label>网址列表(每行一个,# 开头为注释)</label>
|
|||
|
|
<textarea name="urls" rows="5" placeholder="https://www.example.com/ https://www.example.com/page2"></textarea>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div id="scheduleBox" class="hidden box">
|
|||
|
|
<div class="row2">
|
|||
|
|
<div class="field"><label>调度类型</label>
|
|||
|
|
<select name="schedule_type">
|
|||
|
|
<option value="interval">间隔调度(每 N 时间)</option>
|
|||
|
|
<option value="cron">cron 表达式</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
<div class="field check"><label><input name="schedule_enabled" type="checkbox" checked> 启用调度</label></div>
|
|||
|
|
</div>
|
|||
|
|
<div id="intervalBox" class="row2">
|
|||
|
|
<div class="field"><label>每隔</label><input name="interval_value" type="number" value="24"></div>
|
|||
|
|
<div class="field"><label>单位</label>
|
|||
|
|
<select name="interval_unit">
|
|||
|
|
<option value="minutes">分钟</option>
|
|||
|
|
<option value="hours" selected>小时</option>
|
|||
|
|
<option value="days">天</option>
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div id="cronBox" class="field hidden">
|
|||
|
|
<label>cron 表达式(分 时 日 月 周,周 0/7=周日)</label>
|
|||
|
|
<input name="cron" placeholder="0 3 * * * 每天凌晨3点">
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div id="autoBox" class="hidden box">
|
|||
|
|
<div class="field"><label>起始网址 *(系统将自动发现符合规则的链接并爬取)</label>
|
|||
|
|
<input name="seed_url" placeholder="https://example.com/news"></div>
|
|||
|
|
<div class="row2">
|
|||
|
|
<div class="field"><label>包含规则(每行一个,子串或正则)</label>
|
|||
|
|
<textarea name="include" rows="3" placeholder="techpowerup.com/review /news/"></textarea></div>
|
|||
|
|
<div class="field"><label>排除规则</label>
|
|||
|
|
<textarea name="exclude" rows="3" placeholder="login, signup, /tag/, /forum/"></textarea></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="row2">
|
|||
|
|
<div class="field check"><label><input name="same_domain" type="checkbox" checked> 仅爬同域名</label></div>
|
|||
|
|
<div class="field check"><label><input name="use_regex" type="checkbox"> 规则按正则匹配</label></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="row2">
|
|||
|
|
<div class="field"><label>最大页数</label><input name="max_pages" type="number" value="50"></div>
|
|||
|
|
<div class="field"><label>最大爬取深度</label><input name="max_depth" type="number" value="2"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="modal-foot">
|
|||
|
|
<span id="formHint" class="hint"></span>
|
|||
|
|
<button type="button" class="btn ghost" data-close>取消</button>
|
|||
|
|
<button type="submit" class="btn primary">保存</button>
|
|||
|
|
</div>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 任务详情弹窗 -->
|
|||
|
|
<div id="detailModal" class="modal-overlay hidden">
|
|||
|
|
<div class="modal wide">
|
|||
|
|
<div class="modal-head">
|
|||
|
|
<span id="detailTitle">任务详情</span>
|
|||
|
|
<button class="btn ghost sm" data-close-detail>✕</button>
|
|||
|
|
</div>
|
|||
|
|
<div id="detailBody"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 文件预览弹窗 -->
|
|||
|
|
<div id="previewModal" class="modal-overlay hidden">
|
|||
|
|
<div class="modal wide tall">
|
|||
|
|
<div class="modal-head">
|
|||
|
|
<span id="previewTitle">预览</span>
|
|||
|
|
<button class="btn ghost sm" data-close-preview>✕</button>
|
|||
|
|
</div>
|
|||
|
|
<iframe id="previewFrame" sandbox="allow-same-origin"></iframe>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script src="app.js"></script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|