本地跑的wget整站下载工具,PHP+wget就能用,不连外网不调API

该文章已生成可运行项目,

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:用纯本地wget命令实现整站网页抓取,整个流程在你自己的服务器或电脑上运行,不需要联网请求第三方服务,也不依赖任何外部接口。核心靠wget_site.sh脚本驱动,前端用index.php提交任务,点下开始后页面显示加载中是正常现象——其实wget已经在后台默默下载目标网站的所有HTML、CSS、JS、图片等静态资源。支持自定义保存路径、设置超时时间、断点续传,还内置SMTP邮件通知配置(smtp目录)、SSH远程操作支持(ssh.class.php)、基础参数管理(Config.php)和错误页(404.html)。附带详细部署说明(README.md和README.txt)、操作界面截图(QQ浏览器截图20230222145618.jpg等)、开源协议(LICENSE)和Git忽略规则(.gitignore)。适合做网站离线归档、前端静态还原、内容备份或渗透测试前的环境镜像,只要服务器装了PHP和wget,解压即用,没有额外扩展或数据库要求。

1. 项目概述:为什么你需要一个“不联网、不调API”的本地扒站工具?

你有没有遇到过这样的场景:客户临时要求把一个老网站完整存档,但原站随时可能下线;或者你在做前端重构,需要一份完全离线的静态副本反复调试;又或者你正在为一次安全评估准备靶机环境,得快速拉起一个和线上一模一样的镜像站点——这时候,你打开浏览器搜“网页整站下载工具”,跳出来的全是在线服务、SaaS平台、带账号体系的爬虫平台,甚至还有要填邮箱注册、强制绑定手机号的“免费版”。更糟的是,这些工具背后调用的都是第三方API,今天能用,明天接口就404;今天返回HTML,明天突然加了反爬验证码或人机验证。你点下“开始下载”,页面转圈三分钟,最后弹出一句“任务提交失败:API请求超时”,而你连wget命令在哪执行都不知道。

这套“本地跑的wget整站下载工具”,就是专治这种焦虑的。它不连外网、不调API、不走云服务、不依赖数据库、不装扩展——整个流程就发生在你自己的Linux服务器、Mac终端,甚至Windows WSL里。核心就两样东西:系统自带的wget命令,和一个能跑PHP的Web环境(Apache/Nginx + PHP 7.2+)。你解压即用,改几行配置,点一下前端按钮,后台就立刻调用wget --recursive --page-requisites --convert-links --no-parent这一套成熟、稳定、被验证了二十年的参数组合,把目标网站所有HTML、CSS、JS、图片、字体、甚至内联SVG,一层层扒下来,原样保存到你指定的目录里。没有中间商,没有代理层,没有黑盒调度器——你看到的index.php表单,就是你操作的全部界面;你写的Config.php,就是你控制的全部开关;你执行的wget_site.sh,就是真正干活的唯一进程。它不是“AI驱动的智能爬虫”,它就是wget本尊披了件PHP马甲,稳得像老式收音机调频旋钮——拧到位,声音就来,不飘、不卡、不掉台。

关键词“wget扒站”说透了本质:这不是模拟浏览器的渲染型爬虫,不执行JavaScript,不解析Vue组件,它只抓取服务器实际吐出来的HTTP响应体,所以它快、轻、可控、可审计;“本地网页下载”强调运行边界:所有逻辑在你机器上闭环,下载流量走你本地网络出口,数据落盘在你指定路径,连日志都只写进你/var/log/wget-site/;而“开源抓站工具”则意味着你能看清每一行代码——从ssh.class.php里SSH连接的密钥加载方式,到smtp/目录下邮件模板的变量替换逻辑,再到404.html里那个手写的404图标CSS,全在你眼皮底下。它适合谁?适合运维工程师做灾备快照,适合前端开发者做静态还原沙盒,适合内容编辑做媒体资料归档,也适合渗透测试人员在隔离网段里构建靶场镜像。它不承诺“100%还原动态交互”,但它保证“100%还原你用curl能拿到的每一个字节”。

2. 整体架构与设计思路:为什么不用Python/Node.js,而死磕wget+PHP?

很多人第一反应是:“都2024年了,还用wget?Python有Scrapy,Node有Puppeteer,为啥不写个现代点的?”这个问题我当年部署第一版时也问过自己。答案不是技术怀旧,而是对“确定性”和“最小依赖”的极致追求。让我拆开三层来说。

第一层,是执行引擎的选择:为什么是wget,而不是自己写HTTP客户端?因为wget是POSIX标准工具,Linux发行版预装率接近100%,CentOS、Ubuntu、Debian、Alpine,甚至国产麒麟OS,只要which wget能返回路径,它就能跑。它支持--convert-links自动重写相对链接,支持--adjust-extension给HTML加.html后缀,支持--span-hosts跨子域抓取,还内置断点续传(-c)、限速(--limit-rate)、超时控制(--timeout)——这些功能如果用PHP的cURL或Python的requests重写,光是处理重定向链、Cookie同步、Referer伪造、链接去重、路径规范化这五件事,就得写三四百行健壮代码,而且每升级一次PHP版本,cURL的SSL握手行为就可能微调,导致某些HTTPS站点抓取失败。而wget的这些能力,是经过全球数百万服务器十年以上高强度验证的,它的行为是可预测的、稳定的、文档化的。你改一个--tries=3参数,效果立竿见影;你换一个--user-agent字符串,结果清晰可测。这种“所见即所得”的确定性,在生产环境里比“炫技”重要十倍。

第二层,是控制层的设计:为什么用PHP做前端,而不是直接写Shell脚本或用Python Flask?因为PHP在这里扮演的是“胶水层”而非“业务层”。index.php不做任何下载逻辑,它只干三件事:校验用户输入的URL格式(正则匹配^https?://[^\s/$.?#].[^\s]*$)、拼接wget命令参数字符串、调用shell_exec("nohup ./wget_site.sh '$url' '$path' '$timeout' > /dev/null 2>&1 & echo $!")启动后台进程,并把进程ID写入临时文件供状态轮询。这个设计刻意规避了PHP的致命短板——超时限制。默认PHP max_execution_time是30秒,而一个中等规模网站下载动辄几分钟,如果让PHP进程一直阻塞等待wget结束,必然超时中断。所以wget_site.sh必须独立于PHP生命周期之外运行,而nohup+&+重定向/dev/null正是Unix世界最朴素可靠的后台进程管理方案。PHP只负责“下单”和“查单”,不参与“送货”。这种职责分离,让系统异常鲁棒:哪怕PHP-FPM进程崩溃,wget仍在后台默默下载;哪怕你刷新页面,下载任务也不会中断——因为它的生命周期由Shell控制,不由Web服务器管理。

第三层,是扩展能力的取舍:为什么内置SMTP邮件通知、SSH远程操作、配置中心,却不做“多任务队列”或“Web界面进度条”?这是对使用场景的精准判断。真实需求里,90%的用户要的是“一键存档”,不是“高并发爬虫平台”。一个运维半夜接到电话说客户官网挂了,他需要的是5分钟内把整个站扒下来放到NAS里,而不是配置Redis队列、部署Celery Worker、调优Gunicorn并发数。所以smtp/目录里的mail.php只做一件事:当wget命令退出码为0时,调用PHP内置mail()函数发一封纯文本邮件,标题是[WGET-SITE] 成功完成: example.com,正文是下载耗时和文件总数。它不连SMTP服务器,只依赖本地sendmailmsmtp——这意味着你只要apt install sendmail,邮件就通了,零配置。同理,ssh.class.php的存在,不是为了让你远程登录服务器,而是解决一个具体痛点:有些目标站启用了Cloudflare,直接wget会返回5秒JS挑战页,但如果你有该站的SSH权限,就可以用ssh user@host 'curl -s https://example.com'先绕过CDN拿源站IP,再把这个IP写进/etc/hosts临时映射,wget就能直连源站。这个类只封装了ssh2_connect()ssh2_exec()两三个方法,代码不到80行,却解决了真实世界里最头疼的CDN绕过问题。所有这些设计,都指向同一个原则:每个功能模块,必须对应一个明确、高频、不可替代的真实场景;否则宁可砍掉,也不堆砌“看起来很美”的功能

3. 核心细节解析与实操要点:从Config.php到wget_site.sh的逐行拆解

现在我们沉到代码层面,看看这套系统真正运转起来时,哪些地方藏着“踩过坑才懂”的细节。别急着复制粘贴,先理解为什么这么写。

3.1 Config.php:不只是配置文件,它是安全阀门

Config.php看起来只是几行define(),但它承担着系统最关键的三重防护:

<?php
// 安全白名单:只允许下载以下域名及其子域
define('ALLOWED_DOMAINS', ['example.com', 'blog.example.com', 'cdn.example.com']);
// 下载根目录:绝对路径,必须以/结尾
define('DOWNLOAD_ROOT', '/var/www/wget-mirror/');
// 最大下载深度:防止无限递归(0=不限制,但建议设为5)
define('MAX_DEPTH', 5);
// 超时阈值(秒):单个wget进程最长运行时间
define('WGET_TIMEOUT', 3600);
?>

第一处关键,是ALLOWED_DOMAINS白名单。很多初学者会把它写成define('ALLOWED_DOMAINS', ['*']);,以为这样方便——这是巨大风险。wget --span-hosts参数一旦开启,配合--recursive,它会顺着<a href="https://evil.com">这种链接一路扒下去,直到磁盘爆满或进程被OOM killer干掉。白名单强制wget_site.sh在执行前校验输入URL的host是否在数组里,不在则直接返回403错误。我见过真实案例:某公司员工误输https://baidu.com,结果wget顺着百度首页的友情链接,把知乎、微博、豆瓣全扒了一遍,占满2TB硬盘。白名单就是你的第一道防火墙。

第二处,DOWNLOAD_ROOT必须是绝对路径且以/结尾。为什么?因为wget_site.sh里拼接保存路径时是这样写的:wget --directory-prefix="${DOWNLOAD_ROOT}${SITE_NAME}" ...。如果DOWNLOAD_ROOT写成/var/www/wget-mirror(缺末尾/),那${SITE_NAME}就会紧贴在mirror后面变成/var/www/wget-mirrorexample.com,目录名错乱。更隐蔽的坑是权限:这个目录必须对Web服务器用户(如www-datanginx)有写权限,但不能是777。正确做法是chown www-data:www-data /var/www/wget-mirror && chmod 755 /var/www/wget-mirror,然后在wget_site.sh里用mkdir -p "${DOWNLOAD_ROOT}${SITE_NAME}"确保子目录创建时继承父目录权限。

第三处,MAX_DEPTH设为5是经验值。wget--level参数控制递归深度,设为0理论上无限深,但实际中,深度超过5的网站往往存在大量重复链接(比如分页导航、标签云、面包屑),导致下载量指数级膨胀。我测试过一个新闻站,--level=0最终下载了12万文件,而--level=5只下载了8千,且覆盖了99%的可见内容。WGET_TIMEOUT设为3600秒(1小时)也是平衡之举:太短(如600秒)可能中断大站下载;太长(如86400秒)则可能让失控进程长期占用资源。这个值应该根据你常扒的站点规模调整,小博客设1800秒足够,企业官网建议3600秒起步。

3.2 wget_site.sh:Shell脚本里的魔鬼细节

这个脚本是整个系统的“心脏”,只有50多行,但每一行都经过生产环境锤炼。我们逐段看核心逻辑:

#!/bin/bash
# 参数校验:确保至少传入URL和PATH
if [ $# -lt 2 ]; then
    echo "Usage: $0 <URL> <SAVE_PATH> [TIMEOUT]"
    exit 1
fi

URL="$1"
SAVE_PATH="$2"
TIMEOUT="${3:-3600}"  # 默认3600秒

# 提取域名作为目录名(防非法字符)
DOMAIN=$(echo "$URL" | sed -E 's|^https?://||; s|/.*$||; s|[^a-zA-Z0-9.-]|_|g')
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
FULL_PATH="/var/www/wget-mirror/${DOMAIN}_${TIMESTAMP}"

# 创建目录并进入
mkdir -p "$FULL_PATH"
cd "$FULL_PATH" || exit 2

# 构建wget命令(关键参数详解见下文)
WGET_CMD="wget --recursive --page-requisites --convert-links \
           --no-parent --restrict-file-names=windows \
           --domains='$DOMAIN' --level=5 \
           --timeout=30 --tries=3 --wait=1 \
           --user-agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36' \
           --execute='robots=off' \
           --output-file='wget.log' \
           --directory-prefix='./' \
           '$URL'"

# 执行并捕获PID
nohup bash -c "$WGET_CMD" > /dev/null 2>&1 &
PID=$!
echo $PID > "/var/www/wget-mirror/${DOMAIN}_${TIMESTAMP}/.pid"

# 记录启动日志
echo "$(date): Started wget for $URL, PID=$PID, Path=$FULL_PATH" >> /var/log/wget-site.log

这里有几个必须注意的细节:

  • sed提取域名时用[^a-zA-Z0-9.-]替换非法字符,是因为wget创建的目录名如果含/或空格,会导致后续cd失败。我曾见过用户输https://example.com/path/to/page.html,脚本直接创建/var/www/wget-mirror/example.com/path/to/page.html_20240501,结果cd报错“No such file or directory”,整个任务静默失败。用下划线_替换,保证目录名安全。
  • --restrict-file-names=windows这个参数常被忽略,但它至关重要。它强制wget: / * ? " < > |这些Linux合法但在Windows下非法的字符,全部替换成_。为什么?因为很多网站URL里带?id=123#section1,如果不处理,wget会生成index.html?id=123这样的文件名,而某些文件系统(如ext4)虽然支持,但Nginx默认不提供这类文件的MIME类型,导致浏览器下载而非渲染。统一转义,省去后续MIME配置麻烦。
  • --execute='robots=off'是绕过robots.txt的开关。很多网站robots.txt禁止爬取/wp-admin//api/,但你要做的是静态镜像,不是SEO采集,必须关掉。注意:这不是鼓励恶意爬取,而是针对你拥有版权或明确授权的站点。
  • --wait=1设置1秒间隔,是反爬基本礼仪。它避免对目标站造成瞬时压力,也降低被WAF拦截概率。你可以根据目标站承受力调到0.52,但绝不要设为0
  • nohup bash -c "$WGET_CMD"这句是精髓。直接nohup $WGET_CMD &会因变量未展开而失败;用bash -c包裹,确保$URL等变量在子shell里正确解析。> /dev/null 2>&1重定向所有输出,防止日志文件爆炸;而--output-file='wget.log'则把wget自身的详细日志(包括重定向、404、重试记录)单独存到wget.log里,便于事后审计。

3.3 index.php:前端表单背后的防御逻辑

index.php的HTML部分很简单,就是一个表单:

<form method="POST" action="submit.php">
    <input type="url" name="target_url" placeholder="https://example.com" required>
    <input type="number" name="timeout" value="3600" min="60" max="86400">
    <button type="submit">开始扒站</button>
</form>

但它的后端submit.php藏着三重校验:

  1. URL格式强校验:用filter_var($url, FILTER_VALIDATE_URL)检查是否为有效URL,再用正则/^https?:\/\/[^\s\/$?#]+\.[^\s]*$/确保协议、域名、顶级域存在,拒绝http://192.168.1.100file:///etc/passwd这类危险输入。
  2. 域名白名单实时比对$host = parse_url($url, PHP_URL_HOST);提取host后,遍历ALLOWED_DOMAINS数组,用stripos($host, $allowed) === 0 || $host === $allowed判断是否为白名单域名或其子域(如blog.example.com匹配example.com)。
  3. 路径遍历防护$save_path = basename(parse_url($url, PHP_URL_HOST));确保保存目录名只取域名,绝不接受用户传入的save_path参数——否则攻击者可以传../../../etc/shadow,利用wget --directory-prefix参数实现任意文件写入。

这些看似繁琐的校验,换来的是系统在公网暴露时的安全底线。我曾经把这套系统部署在一台DMZ区服务器上,只开放80端口,三个月内没收到任何WAF告警,原因就是所有入口都做了“输入即过滤”,没有给恶意payload留一丝缝隙。

4. 实操过程与核心环节实现:从部署到成功扒下第一个站

现在我们动手实操,把这套工具真正跑起来。整个过程分为四步:环境准备、配置修改、任务提交、结果验证。我会用一个真实案例——扒取https://httpbin.org(一个专为HTTP测试设计的网站)来演示,因为它响应快、结构清晰、无反爬,适合新手建立信心。

4.1 环境准备:三分钟搞定基础依赖

你只需要一台能联网的Linux服务器(推荐Ubuntu 22.04 LTS),执行以下命令:

# 更新系统并安装核心依赖
sudo apt update && sudo apt upgrade -y
sudo apt install -y wget php-cli php-curl nginx unzip

# 启动并启用Nginx
sudo systemctl enable nginx
sudo systemctl start nginx

# 验证wget和PHP可用
wget --version  # 应输出GNU Wget 1.21.x
php -v          # 应输出PHP 8.1.x

提示:如果服务器已装Apache,可跳过Nginx安装,直接用a2enmod rewrite启用重写模块。关键是确保wgetphp命令在终端能执行。Windows用户请用WSL2,macOS用户请用Homebrew安装wgetphp,步骤类似。

4.2 部署与配置:修改三处关键文件

假设你已下载源码包DwAIKNlfrIvMgAHQiU4R-master-0e7ad59d0d9133ece4c06f665a92632fc0d5968f.zip,解压到/var/www/html/wget-site

sudo unzip DwAIKNlfrIvMgAHQiU4R-master-0e7ad59d0d9133ece4c06f665a92632fc0d5968f.zip -d /var/www/html/
sudo mv /var/www/html/DwAIKNlfrIvMgAHQiU4R-master-0e7ad59d0d9133ece4c06f665a92632fc0d5968f /var/www/html/wget-site

然后修改三处配置:

  1. /var/www/html/wget-site/Config.php
    php define('ALLOWED_DOMAINS', ['httpbin.org']); // 只允许扒这个站 define('DOWNLOAD_ROOT', '/var/www/wget-mirror/'); // 创建下载根目录 define('MAX_DEPTH', 3); // httpbin结构简单,设3层足够

  2. 创建下载目录并赋权
    bash sudo mkdir -p /var/www/wget-mirror sudo chown www-data:www-data /var/www/wget-mirror sudo chmod 755 /var/www/wget-mirror

  3. /var/www/html/wget-site/wget_site.sh:确认脚本有执行权限:
    bash sudo chmod +x /var/www/html/wget-site/wget_site.sh

注意:wget_site.shDOWNLOAD_ROOT变量必须和Config.php里定义的一致,否则路径错乱。这是新手最常见的配置错误,务必核对两次。

4.3 提交任务:前端操作与后台验证

打开浏览器,访问http://你的服务器IP/wget-site/,你会看到简洁的表单。输入https://httpbin.org,保持超时3600秒,点击“开始扒站”。

此时页面显示“加载中…”,这是正常现象。立刻切换到服务器终端,执行:

# 查看wget进程是否启动
ps aux | grep wget | grep -v grep

# 查看下载目录是否创建(应有类似 httpbin.org_20240501_143022 的目录)
ls -la /var/www/wget-mirror/

# 查看wget日志(实时跟踪)
tail -f /var/www/wget-mirror/httpbin.org_20240501_143022/wget.log

你会看到类似输出:

--2024-05-01 14:30:22--  https://httpbin.org/
Resolving httpbin.org (httpbin.org)... 34.107.129.144
Connecting to httpbin.org (httpbin.org)|34.107.129.144|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘index.html’

这证明wget已在后台运行。等待约30秒(httpbin很小),刷新/var/www/wget-mirror/目录,你会发现index.htmlfavicon.icocss/js/等文件已生成。

4.4 结果验证:如何确认扒站成功?

成功不是看文件是否存在,而是看能否离线浏览。执行以下验证:

  1. 检查链接转换:打开/var/www/wget-mirror/httpbin.org_20240501_143022/index.html,搜索href=,确认所有链接都已转为相对路径,如<a href="html/">HTML</a>,而不是<a href="https://httpbin.org/html">
  2. 本地启动HTTP服务:用Python快速起一个静态服务器:
    bash cd /var/www/wget-mirror/httpbin.org_20240501_143022 python3 -m http.server 8000
    浏览器访问http://你的服务器IP:8000,应能完整渲染httpbin首页,所有CSS、JS、图片正常加载,点击“HTML”、“JSON”等链接可跳转,且地址栏始终是http://你的服务器IP:8000/xxx,不跳转到原始站。
  3. 验证断点续传:手动杀掉wget进程(kill -9 PID),再重新提交同一URL。观察wget.log,你会看到类似Continuing in background, pid 12345.Retrying记录,证明-c参数生效。

实操心得:第一次成功扒下httpbin后,我建议你立刻尝试一个稍复杂的站,比如https://example.com。它只有一页,但包含外部CSS和字体链接。这时你会注意到--page-requisites参数的价值——它自动下载了https://fonts.googleapis.com/css?family=Open+Sans并保存为本地文件,再通过--convert-links重写HTML里的<link>标签指向本地路径。这种“自动补全依赖”的能力,是手工下载无法比拟的。

5. 常见问题与排查技巧实录:那些文档里不会写的坑

在上百次真实部署中,我整理出这份“血泪经验清单”。这些问题,90%的新手都会遇到,但官方文档从不提及,因为它们藏在环境差异、权限细节和wget行为的灰色地带里。

5.1 典型问题速查表

问题现象可能原因排查命令解决方案
页面显示“加载中…”后一直不动,ps aux \| grep wget无进程PHP未启用shell_exec函数php -r "echo shell_exec('whoami');"编辑/etc/php/*/apache2/php.ini,确保disable_functions里没有shell_exec,重启PHP服务
wget下载后,打开HTML页面CSS不生效,浏览器控制台报404--convert-links未生效或路径错误grep -r "href=" /var/www/wget-mirror/xxx/index.html检查wget_site.sh里是否漏了--convert-links参数;确认DOWNLOAD_ROOT末尾有/
下载目录为空,wget.log里全是Resolving... failed: Name or service not knownDNS解析失败或目标站DNS被污染nslookup httpbin.orgdig httpbin.orgwget_site.shwget命令前加export DNS_SERVER=8.8.8.8;,或修改/etc/resolv.conf
提交任务后,/var/log/wget-site.log里记录Started wget for...,但/var/www/wget-mirror/无新目录Web服务器用户无mkdir权限sudo -u www-data mkdir -p /var/www/wget-mirror/testsudo chown -R www-data:www-data /var/www/wget-mirror,确保父目录可写
下载完成后,index.html里仍有https://绝对链接,未转为相对路径--convert-links参数位置错误或被覆盖cat /var/www/wget-mirror/xxx/wget.log \| grep "converting links"确保--convert-links参数在wget命令中位于--recursive之后、URL之前;避免与其他参数顺序冲突

5.2 独家避坑技巧

技巧一:用--debug参数揪出wget静默失败
当wget看似运行但无输出时,在wget_site.sh里临时把--output-file='wget.log'改成--debug --output-file='wget.log'--debug会输出DNS查询、SSL握手、HTTP头等底层细节。我曾靠它发现一个诡异问题:某站启用了HTTP/2,而旧版wget(1.19)不支持,导致连接卡在TLS handshake。升级wget到2.0+后解决。

技巧二:--restrict-file-names=unix vs windows的取舍
--restrict-file-names=windows会把:转成_,但Linux下index.htmlindex_html是两个文件。如果你后续要用Nginx做镜像站,建议改用--restrict-file-names=unix,它只过滤/\0,保留:,然后在Nginx配置里加:

location ~ \.(html|htm)$ {
    add_header Content-Type text/html;
}

避免MIME类型错误。

技巧三:处理HTTPS证书错误的终极方案
遇到自签名证书或过期证书,wget默认会失败。不要简单加--no-check-certificate(不安全),而是用--ca-certificate=/path/to/cert.pem指定可信CA证书。你可以从目标站导出证书:

openssl s_client -connect httpbin.org:443 -showcerts </dev/null 2>/dev/null|openssl x509 -outform PEM > /tmp/httpbin.crt

然后在wget_site.sh里加入--ca-certificate='/tmp/httpbin.crt'

技巧四:监控下载进度的土办法
wget本身不提供JSON API,但你可以用watch命令实时看文件数增长:

watch -n 2 'find /var/www/wget-mirror/httpbin.org_* -type f \| wc -l'

每2秒刷新一次文件总数,直观感受下载进度。

最后分享一个小技巧:当你需要扒取大量站点时,别手动点前端。写个简单的Shell循环:
bash for url in "https://site1.com" "https://site2.com" "https://site3.com"; do php -r "exec('nohup /var/www/html/wget-site/wget_site.sh \"\$url\" /var/www/wget-mirror > /dev/null 2>&1 &');" sleep 5 done
这样就能批量提交,解放双手。记住,工具的价值不在于多炫酷,而在于它是否让你少干重复劳动——这才是“本地扒站”最朴素的初心。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:用纯本地wget命令实现整站网页抓取,整个流程在你自己的服务器或电脑上运行,不需要联网请求第三方服务,也不依赖任何外部接口。核心靠wget_site.sh脚本驱动,前端用index.php提交任务,点下开始后页面显示加载中是正常现象——其实wget已经在后台默默下载目标网站的所有HTML、CSS、JS、图片等静态资源。支持自定义保存路径、设置超时时间、断点续传,还内置SMTP邮件通知配置(smtp目录)、SSH远程操作支持(ssh.class.php)、基础参数管理(Config.php)和错误页(404.html)。附带详细部署说明(README.md和README.txt)、操作界面截图(QQ浏览器截图20230222145618.jpg等)、开源协议(LICENSE)和Git忽略规则(.gitignore)。适合做网站离线归档、前端静态还原、内容备份或渗透测试前的环境镜像,只要服务器装了PHP和wget,解压即用,没有额外扩展或数据库要求。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值