Web 机器人(通常称为网络爬虫、蜘蛛)是一种自动遍历互联网并下载网页的工具,最常见用途是供搜索引擎建立索引。接下来我会用一个“程序员技术博客搜索引擎”的例子来讲解,假设我们做一个专门针对程序员技巧博客的垂直搜索引擎,叫CodeSearch,在通用搜索引擎里泛泛地找。就是程序员能够用Web机器人快速找到高质量的解决方案,而不
1.爬虫及爬行方式
1.1 根集
互联网这么大,像一片茫茫大海,爬虫第一个网址应该去哪?我们不能让爬虫瞎逛,得给它一个“初始任务清单”,这个清单就是根集。
建立根集:你手动收集一个初始博客列表,比如:
https://tech.meituan.com/(美团技术博客)
https://aws.amazon.com/cn/blogs/china/(AWS中国博客)
https://blog.github.com/(GitHub官方博客)https://coolshell.cn/ (酷壳 - 陈皓的个人博客)
这些就是爬虫的“起点地图”,也就是根集。
1.2 链接的提取以及相对链接的标准化
链接提取:爬虫下载一个页面后,会像浏览器一样解析HTML,寻找所有超链接标签(如 <a href="...">, <img src="...">, <link href="...">)。
相对链接标准化(绝对化):这是关键步骤。HTML中的链接往往是相对的(如 about.html, /images/logo.png, ../news/)。爬虫必须将它们转换为完整的绝对URL(如 https://www.example.com/about.html)。
转换规则:依赖于页面的 基础URL(Base URL)。基础URL通常就是当前页面的URL,但如果页面中包含 <base href="..."> 标签,则以此标签指定的URL为准。
爬虫开始工作:
第一站:爬虫访问
https://tech.meituan.com/。下载页面:它把首页的HTML代码下载下来。
提取链接:它解析HTML,找到所有
<a href="...">标签。比如,它发现了:
https://tech.meituan.com/2023/09/01/a-new-article-about-java.html(一篇新文章)
/2023/08/15/an-older-article-about-microservices.html(一个相对链接)标准化链接:爬虫将第二个相对链接补全为绝对链接:
https://tech.meituan.com/2023/08/15/an-older-article-about-microservices.html。记录与排队:爬虫把这两个新文章链接加入待爬取队列。同时,把美团的首页标记为"已访问",避免下次再来。
1.3 避免环路
防止爬虫在几个URL之间无限循环爬取,浪费资源。比如A页面链接到B,B链接到C,C又链接回A。
CodeSearch否已经在这个集合里。如果已经访问过,则跳过。这确保了CodeSearch的爬虫不会在博客的导航栏链接中打转。就是中的爬虫会维护一个“已访问URL集合”。每次准备爬取一个新URL前,都会检查它
1.4 循环与复制
同一个资源可能有多个URL(别名),导致爬虫重复抓取相同内容。例如,http://example.com和 http://www.example.com 可能指向同一站点;index.html 被省略的情况等。
CodeSearch爬虫如果不处理别名,这浪费了带宽和存储空间,降低了索引效率。在美团博客抓取中,
https://tech.meituan.com/和https://tech.meituan.com/index.html可能会被当作两个不同的页面被抓取两次。
1.5 面包屑留下的痕迹
爬虫在爬行过程中记录下来的路径信息,用于调试和分析爬虫行为,或者在出现环路时帮助诊断问题。
场景:诊断“爬虫卡死”或“陷入循环”
面包屑最经典的用途。假设你的CodeSearch爬虫在爬取某个博客时,CPU占用率很高,但新抓到的文章数量却不再增长。它好像“卡死”在某个地方了。就是这
没有面包屑:你只知道爬虫出了问题,但无从下手。
有面包屑:你打开最近几分钟的爬行日志(面包屑),可能会立刻发现如下模式:
... (前面的日志正常) [时间] 10:05:30 | [动作] 已爬取 | [URL]https://tech.meituan.com/archive/2023/10/ [时间] 10:05:31 | [动作] 发现链接 | [URL]https://tech.meituan.com/archive/2023/11/ | [来源页面] https://tech.meituan.com/archive/2023/10/ [时间] 10:05:32 | [动作] 已爬取 | [URL]https://tech.meituan.com/archive/2023/11/ [时间] 10:05:33 | [动作] 发现链接 | [URL]https://tech.meituan.com/archive/2023/12/ | [来源页面] https://tech.meituan.com/archive/2023/11/ [时间] 10:05:34 | [动作] 已爬取 | [URL]https://tech.meituan.com/archive/2023/12/ [时间] 10:05:35 | [动作] 发现链接 | [URL]https://tech.meituan.com/archive/2024/01/ | [来源页面] https://tech.meituan.com/archive/2023/12/ ... (日志在持续生成明年、后年的月归档页面,无穷无尽)问题诊断:你一眼就看出来了!爬虫掉进了一个“动态虚拟Web空间新内容,不停地爬取,其实页面结构都差不多,内容价值很低,却消耗了你大量的资源。就是”的陷阱。这个博客的归档页面可以无限地生成“下一个月”的链接。爬虫以为那
解决动态虚拟Web空间的手段:
策略1:URL模式识别与规则定义
做法:在爬虫代码中预先定义黑名单或规则。
示例:
忽略特定目录:如果发现URL中包含
/calendar/或/archive/,且深度超过2级,则停止跟踪该分支的链接。限制分页:对于包含
?page=或&page=参数的URL,只爬取前10页。例如,如果page=11,则直接丢弃该URL。清洗无关参数:在规范化URL时,主动移除已知的跟踪参数,如
utm_*,sessionid,source等。这样article.html?utm_source=xxx就会被规范化为article.html,从而避免重复。策略2:内容相似度检测
做法:当爬虫下载一个新页面后,计算这个页面的“指纹”(例如,提取正文文本的哈希值)与已爬取页面的指纹进行比对。
示例:爬虫发现
?page=1和?page=2的两个页面,虽然URL不同,但页面结构模板(导航栏、侧边栏)的相似度高达95%,只有中间的文章列表内容不同。如果连续多个页面结构高度相似,爬虫可以判断可能进入了列表页循环,从而主动停止或降低优先级。策略3:设置爬取边界
做法:为整个爬虫任务设置硬性限制。
示例:
最大深度:从根目录开始,最多爬取10层链接。这能有效防止在无限目录结构中陷得太深。
单站最大页面数:对于任何一个域名,最多只爬取10,000个页面。这能防止在一个拥有海量低质量页面的站点上浪费所有时间。
策略4:遵守robots.txt
做法:虽然
robots.txt不能解决所有问题,但聪明的网站管理员会在其中指明不希望被爬取的部分,比如Disallow: /search?*(禁止爬取所有搜索结果页)。CodeSearch爬虫严格遵守这一点,可以避免很多麻烦。
1.6 规范化URL
这是解决环路和复制难题的技术手段。通过一套规则将URL转换成标准格式,从而判断两个URL是否等价。
为什么需规范化?一个严重后果的例子
假设CodeSearch爬虫遇到一篇美团的科技文章,它可以经过以下各种URL访问:
https://tech.meituan.com/article.html
https://tech.meituan.com/ARTICLE.html(大小写不同)
https://tech.meituan.com/./article.html(多了一个./)
https://tech.meituan.com:443/article.html(显式指定了HTTPS默认端口)
https://TECH.MEITUAN.COM/article.html(域名大写)如果没有规范化:
你的爬虫会认为这5个URL是5个不同的页面,它会:
下载5次完全相同的文章内容。
存储5份重复的HTML。
为这5份内容分别建立索引。
在搜索结果中,这篇相同的文章可能会出现5次,挤占其他结果的位置。
这会造成灾难性的资源浪费(带宽、存储、计算力)和搜索质量下降。
常见的规范化规则:
规则1:协议和主机名小写化
原因:域名和协议名不区分大小写。
操作:将所有字母转换为小写。
示例:
HTTPS://TECH.MEITUAN.COM/->https://tech.meituan.com/规则2:默认端口号剔除
原因:
:80是HTTP的默认端口,:443是HTTPS的默认端口。显式写在URL里和省略是一样的。操作:如果URL中含有默认端口号,则将其移除。
示例:
https://tech.meituan.com:443/article.html->https://tech.meituan.com/article.html
http://tech.meituan.com:80/article.html->http://tech.meituan.com/article.html规则3:路径中的“.”和“..”解析
原因:
./代表当前目录,../代表上级目录。它们需要被解析成最简单的路径形式。操作:像操作系统解析路径一样处理它们。
示例:
https://tech.meituan.com/./blog/./article.html->https://tech.meituan.com/blog/article.html
https://tech.meituan.com/blog/2023/../article.html->https://tech.meituan.com/blog/article.html(先进入2023,再退出,等于在blog目录)规则4:路径末尾斜杠的统一
原因:对于服务器来说,
/dir和/dir/有时指向同一个资源(特别是当/dir是一个目录时)。操作:这是一个需要谨慎处理的规则。常见策略是:如果资源看起来像一个目录(路径最后一部分没有文件扩展名),则为其添加斜杠;或者更简单的策略是保留原样,但必须保持一致。大多数爬虫会选择后者,即不主动添加或删除,但将
/dir和/dir/视为不同的URL,并依赖其他规则(如服务器重定向)来处理。示例:如果服务器将
https://tech.meituan.com/blog重定向到https://tech.meituan.com/blog/,那么爬虫只需要记录最终的那个URL。规则5:百分比编码和解码
原因:URL中某些字符(如空格、中文)需要被编码(如空格变成
%20)。但有时编码不统一。操作:对URL中的非ASCII字符或保留字符进行标准化编码。
示例:
https://example.com/文件 名.pdf(包含空格和中文字符)规范化后可能变为:
https://example.com/%E6%96%87%E4%BB%B6%20%E5%90%8D.pdf这样,无论原始链接里的编码是什么样,最终都会变成该统一的形式。
规则6:查询字符串的排序
原因:查询参数的顺序通常不影响页面内容。
?a=1&b=2和?b=2&a=1可能返回相同页面。操作:将查询参数按字母顺序排序。
示例:
https://example.com/search?b=2&a=1->https://example.com/search?a=1&b=2注意:这个规则非常危险! 因为极少数网站的服务器程序可能依赖参数顺序。所以现代爬虫通常不做排序,而是将不同顺序的URL视为不同,除非有明确证据表明它们等价。
2.机器人的HTTP
2.1 识别请求首部
爬虫应该在HTTP请求中明确标识自己,通常通过User-Agent字段。例如:User-Agent: CodeSearch-Bot/1.0 (+http://www.codesearch.com/bot)。
CodeSearch爬虫直接封禁IP。就是:这既是礼貌,也是方便网站管理员识别流量来源。如果CodeSearch的爬虫行为有问题,管理员可以根据这个标识联系你们,而不
2.2 虚拟主机
一台服务器可能托管多个网站(虚拟主机),依靠HTTP请求中的Host首部来区分。否则,服务器可能无法返回正确的网站内容,甚至返回错误。
2.3 条件请求
爬虫可以发送带条件(如If-Modified-Since或ETag)的请求,询问页面是否自上次抓取后有变更。如果没变,服务器会返回304 Not Modified,节省了传输完整页面内容的带宽。
2.4 对响应的处理
爬虫需要正确处理各种HTTP状态码。例如,遇到301 Moved Permanently(永久重定向)应更新书签;遇到404 Not Found(未找到)应从待爬队列中移除该URL。
2.5 User-Agent导向
需要意识到,它抓取到的HTML可能和用户在浏览器中看到的不一样。假如某些重要内容只对浏览器展示,可能需要更高级的工艺(如无头浏览器)来渲染页面后再抓取。
a) 设备适配与响应式设计
目的:为不同设备(如PC、手机、平板)给出最合适的页面布局和内容。
如何工作:服务器检测到来自手机User-Agent(如包含
Mobile或Android)的请求时,会返回移动端版本的HTML(通常代码更简洁,布局不同)。检测到PC浏览器User-Agent时,则返回功能更复杂的桌面版。b) 浏览器兼容性
目的:为老旧的浏览器(如IE)返回兼容性更好的、作用简化的代码,而为现代浏览器返回利用新特性的丰富内容。
对爬虫的影响:如果你的爬虫伪装成一个过时浏览器的User-Agent,可能会得到一个“降级”版本的页面,缺少你想要的数据。
c) 反爬虫机制
目的:这是最需要爬虫注意的一点。网站管理员为了阻止恶意的爬虫占用资源、抓取数据,会采取以下措施:
识别与拦截:维护一个“黑名单”,列出已知的爬虫或恶意工具的User-Agent(如
python-requests,curl,各种爬虫库的名称)。一旦检测到这些User-Agent,服务器可能直接返回403 Forbidden(禁止访问)、404 Not Found(假装页面不存在)或者一个充满错误信息的页面。返回虚假资料:更狡猾的做法是,对识别出的爬虫返回看似正常但实则是虚假、混乱的数据,误导爬虫。
挑战页面:返回一个繁琐的JavaScript验证页面(如CAPTCHA验证码),而普通的爬虫无法处理。
3.行为不当的机器人
指不遵守规则、贪婪、具有攻击性的爬虫。例如,爬取速度过快导致网站瘫痪、无视robots.txt、抓取敏感信息等。
为了必须避免成为“行为不当的机器人”。它应该:
设置爬取延迟:在两次请求之间暂停一段时间(如1-2秒)。
严格遵守
robots.txt。只抓取公开内容:不尝试登录或抓取私有文章,否则不仅会被网站封禁,损害声誉,还可能面临法律风险。
4.拒绝机器人访问
4.1 robots.txt文件
robots.txt记录这是网站管理员控制爬虫行为的标准机制,robots.txt是放在网站根目录下的一个文本文件,用于告知爬虫哪些目录或文件可以/不可以抓取。
User-Agent: *
Disallow: /private/ //不允许private下的页面被抓取
Allow: /public/ //允许public下的文件被抓取
CodeSearch爬虫:在爬取任何网站(如
https://tech.meituan.com/)之前,CodeSearch爬虫必须先访问https://tech.meituan.com/robots.txt。如果文件中写着Disallow: /comments/,爬虫就会自动跳过所有评论页面,避免陷入无限翻页的陷阱。它还会缓存这个文件一段时间,避免每次抓取前都去请求。
4.2 HTML的robot-control元标签
网页开发者可以在HTML的<meta>标签中直接声明是否允许爬虫索引本页或跟踪链接。例如:<meta name="robots" content="noindex, nofollow">。
CodeSearch爬虫:爬虫下载并解析HTML后,在提取内容之前,会先检查
<meta>标签。如果看到noindex,即使文章内容很好,爬虫也会放弃索引该页面,尊重开发者的意愿。
5.全文索引
即倒排索引按关键词索引(“Java”->[文章A, 文章D], “高并发”->[文章A])。就是。它不是按文档顺序(文章A,文章B...)存储,而
假设爬虫带回了三篇文章:
文章A(来自美团):标题《Java高并发编程实战》,内容关键讲「Java」、「线程池」、「锁」
文章B(来自酷壳):标题《深入理解Linux系统调用》,内容讲「Linux」、「内核」、「架构调用」。
文章C(来自GitHub):标题《GitHub Actions自动化部署指南》,内容讲「CI/CD」、「GitHub」、「Docker」。
你的搜索引擎不会把整篇文章存起来就完事了,它会创建一个「倒排索引」,就像一本超级目录:
「Java」 -> [出现在文章A]
「Linux」 -> [出现在文章B]
「GitHub」 -> [出现在文章C]
「架构」 -> [出现在文章B(平台调用), 文章C(操作系统)]
「高并发」 -> [出现在文章A]
现在,你的「CodeSearch」网站上线了。一个程序员遇到了挑战,前来搜索。 场景:程序员想学习「Java高并发」,他在你的网站搜索框输入了:Java 高并发教程。 你的搜索引擎对查询词进行分词,提取出核心关键词:Java和高并发。 它去查阅那种“倒排索引”,发现「Java」对应文章A,「高并发」也对应文章A, 它确定文章A是同时包含这两个关键词的最相关结果。 它把文章A的标题、摘要和链接展示给用户,排在结果的第一位。 用户直接点击链接,阅读了美团技术博客那篇高质量文章,快速应对了问题。
6.欺诈
指SEO作弊行为,如关键词堆砌、隐藏文字、制造垃圾链接等,企图不公平地提升排名。
CodeSearch应用:由于CodeSearch专注于高质量技术博客,初期可能较少遇到恶意SEO。但随着知名度提升,必然有人想借助作弊手段让自己的文章排在前面。CodeSearch的排名算法必须包含反欺诈机制,能够识别并惩罚这些行为,确保结果的质量和公平性。
浙公网安备 33010602011771号