一次爬取网站的经历
前言
一次使用 wget 爬取网站资源的经历。
背景
昨天晚上在看 技术摘抄 的时候,发现该网站因为收到 Google 相关通知,不久会被关闭,所以我就想着能不能将整个网站的内容保存下来,后面还可以看。
经过后面一通 f12 分析,我发现它不是常规的前后端通过 ajax 请求来进行数据交互的,而是类似于 hexo 这类博客,将 markword 文件渲染为 html 进行展示,所以我想出来的唯一方法就是将 html 包括相关的 css、js、图片等全部下载下来。
这里会使用到一个工具 wget,然后编写了一些脚本,在我自己的服务器上跑了大概 1 天,成功的下载了所有的内容。
之所以要跑一天,是因为这个网站应该是基于 cloudflare 做了请求的限制,所以我每次的请求都必须要等待一段时间。
下面就将我这个过程中用到的 sh 脚本分享出来,希望大家慎用。
wget 批量爬取资源
首先 wget 命令是:
wget -r -l inf --no-parent --accept=html,css,jpg,jpeg,png,gif,md -e robots=off -w 5 -x -np -pk "download_url"
解释一下:
-r
:启用递归下载。-l inf
:设置递归的最大深度为无限。--no-parent
:确保 wget 不会爬取到指定目录之外的上级目录。--accept=html,css,jpg,jpeg,png,gif,md
:只接受特定类型的文件。-e robots=off
:忽略站点的 robots.txt 文件。-w 5
:在每次请求之间等待 5 秒钟,这就是避免因为请求过于频繁而被封禁 IP 地址。-x
:使用原来的目录结构保存文件,这样下载的内容会按照原网站的目录结构进行组织。-np
:不追溯到父级目录。-pk
:下载显示 HTML 页面所必需的所有文件。比如,如果一个 HTML 页面包含图片、样式表等,那么这些也会一并被下载下来。"download_url"
:这就是要下载的起始 URL。
在下载过程中,我们肯定不能手动输入 download_url,所以我会提前将网站的所有文章链接写到一个 txt 文件,其次,在下载完成后记录日志,方便后面如果哪里有问题好排查。
最后,启动 sh 时请使用 nohup,否则关掉终端后 sh 命令就会停止了,如下:
nohup ./download.sh index.txt &
download.sh 参考:
#!/bin/sh
# 参数是包含 URL 的文本文件名称
URL_FILE="$1"
# 日志文件名
LOG_FILE="download_log.txt"
# 清空或创建日志文件
> "$LOG_FILE"
# 读取 URL 文件并下载每个 URL
while IFS= read -r URL; do
if [ -n "$URL" ]; then # 确保 URL 不为空
echo "Downloading from: $URL" | tee -a "$LOG_FILE"
# 使用 wget 下载 URL,并将输出重定向到日志文件
wget -r -l inf --no-parent --accept=html,css,jpg,jpeg,png,gif,md -e robots=off -w 5 -x -np -pk "$URL" 2>&1 | tee -a "$LOG_FILE"
# 检查 wget 的退出状态
if [ $? -eq 0 ]; then
echo "Success: $URL" | tee -a "$LOG_FILE"
else
echo "Failure: $URL" | tee -a "$LOG_FILE"
fi
fi
done < "$URL_FILE"
echo "All downloads completed." | tee -a "$LOG_FILE"
将 .md 修改为 .html
将资源下载下来后,文件的后缀是 .md,但是里面的内容实际是 html,所以我们将所有的 .md 后缀修改为 .html,如下:
#!/bin/sh
# 检查是否提供了一个参数
if [ -z "$1" ]; then
echo "请提供一个目录作为参数"
exit 1
fi
# 定义目录变量
dir="$1"
# 使用 find 查找 .md 文件,并对每个找到的文件执行 mv 命令更改扩展名
find "$dir" -type f -name "*.md" | while read file; do
# 获取文件的基本名称(不含扩展名)
base="${file%.md}"
# 重命名文件
mv "$file" "${base}.html"
done