v1.0.14: 自动爬取支持深度/页数无限制(默认0/1000), 待爬链接持久化缓存队列(停止后续爬), 起始网址不去重, 清空缓存API
This commit is contained in:
+19
-4
@@ -434,7 +434,8 @@ async function openEdit(tid) {
|
||||
f.elements["exclude"].value = (t.auto.exclude || []).join("\n");
|
||||
f.elements["same_domain"].checked = t.auto.same_domain !== false;
|
||||
f.elements["use_regex"].checked = !!t.auto.use_regex;
|
||||
f.elements["max_pages"].value = t.auto.max_pages ?? 200;
|
||||
f.elements["max_pages"].value = t.auto.max_pages ?? 1000;
|
||||
f.elements["max_depth"].value = t.auto.max_depth ?? 0;
|
||||
}
|
||||
syncScheduleUI();
|
||||
$("formHint").textContent = t.running
|
||||
@@ -480,7 +481,8 @@ async function submitForm(e) {
|
||||
exclude: splitLines(f.elements["exclude"].value),
|
||||
same_domain: f.elements["same_domain"].checked,
|
||||
use_regex: f.elements["use_regex"].checked,
|
||||
max_pages: parseInt(f.elements["max_pages"].value) || 200,
|
||||
max_pages: parseInt(f.elements["max_pages"].value) || 0,
|
||||
max_depth: parseInt(f.elements["max_depth"].value) || 0,
|
||||
};
|
||||
}
|
||||
if (mode === "scheduled") {
|
||||
@@ -542,7 +544,10 @@ function renderDetail() {
|
||||
<span>任务ID: <b>${t.id}</b></span>
|
||||
<span>创建: <b>${fmtTime(t.created_at)}</b></span>
|
||||
<span>输出: <b>${esc(cfg.out_dir || "out/" + t.id)}</b></span>
|
||||
${t.mode === "auto" ? `<span>起始: <b>${esc((t.auto && t.auto.seed_url) || "")}</b></span>` : ""}
|
||||
${t.mode === "auto" ? `
|
||||
<span>起始: <b>${esc((t.auto && t.auto.seed_url) || "")}</b></span>
|
||||
<span>待爬缓存: <b>${(t.auto && (t.auto.pending || []).length) || 0}</b> 条(停止后可继续爬取)</span>
|
||||
<span>已爬: <b>${(t.auto && (t.auto.visited || []).length) || 0}</b> 页</span>` : ""}
|
||||
</div>`;
|
||||
|
||||
let sched = "";
|
||||
@@ -563,7 +568,8 @@ function renderDetail() {
|
||||
<button class="btn" onclick="actTask('${t.id}','pause')">⏸ 暂停</button>
|
||||
<button class="btn danger" onclick="actTask('${t.id}','stop')">⏹ 终止</button>`
|
||||
: `<button class="btn primary" onclick="actTask('${t.id}','start')">▶ 立即执行</button>`}
|
||||
${t.mode === "auto" ? `<button class="btn" onclick="probeTask('${t.id}')">🧪 试爬取</button>` : ""}
|
||||
${t.mode === "auto" ? `<button class="btn" onclick="probeTask('${t.id}')">🧪 试爬取</button>
|
||||
<button class="btn" ${t.running ? "disabled" : ""} onclick="clearCache('${t.id}')">🧹 清空缓存</button>` : ""}
|
||||
<button class="btn" onclick="openEdit('${t.id}')">✏️ 编辑配置</button>
|
||||
</div>`;
|
||||
|
||||
@@ -719,6 +725,15 @@ async function probeTask(tid) {
|
||||
} catch (e) { toast(e.message, true); }
|
||||
}
|
||||
|
||||
async function clearCache(tid) {
|
||||
if (!confirm("清空待爬缓存与已爬记录?\n下次运行将从起始网址重新开始爬取。")) return;
|
||||
try {
|
||||
const r = await api(`/api/tasks/${tid}/clear_cache`, { method: "POST" });
|
||||
toast(r.msg || "已清空");
|
||||
openDetail(tid);
|
||||
} catch (e) { toast(e.message, true); }
|
||||
}
|
||||
|
||||
function renderProbe(r) {
|
||||
const body = $("probeBody");
|
||||
if (!r.ok) {
|
||||
|
||||
+6
-2
@@ -132,8 +132,12 @@
|
||||
<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="field"><label>最大页数(安全上限,达到后自动停止;不设深度限制,会一直递归爬取到无新链接可爬为止)</label>
|
||||
<input name="max_pages" type="number" value="200"></div>
|
||||
<div class="row2">
|
||||
<div class="field"><label>最大爬取深度(0=无限制,N=只爬 N 层)</label>
|
||||
<input name="max_depth" type="number" min="0" value="0"></div>
|
||||
<div class="field"><label>最大页数(0=无限制,默认 1000 作安全上限)</label>
|
||||
<input name="max_pages" type="number" min="0" value="1000"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-foot">
|
||||
|
||||
Reference in New Issue
Block a user