在采集网站的时候,还会遇到一些比数据显示在浏览器上却抓取不出来更令人沮丧的事 情。也许是向服务器提交自认为已经处理得很好的表单却被拒绝,也许是自己的 IP 地址不知道什么原因直接被网站封杀,无法继续访问。
在这本书里,我已经写了一堆方法来处理网站抓取的难点(提交表单,抽取和清理数据, 执行 JavaScript,等等)。这一章将继续介绍更多的知识点,尽管属于不同的主题(HTTP headers、CSS 和 HTML 表单等),但这些知识点的共同目的都是为了克服网站阻止自动采集这个障碍。
12.1 道德规范
12.2 让网络机器人看起来像人类用户
网站防采集的前提就是要正确地区分人类访问用户和网络机器人。虽然网站可以使用很多 识别技术(比如验证码)来防止爬虫,但还是有一些十分简单的方法,可以让你的网络机 器人看起来更像人类访问用户。
12.2.1 修改请求头
requests 模块是一个设置请求头的利器。HTTP 的请求头是在你每次向网络服务器发送请求时,传递的一组属性和配置信息。HTTP 定义了十几种古怪的请求头类型,不过大多数都不常用。只有下面的七个字段被大多数浏览器用来初始化所有网络请求
属 性 | 内 容 |
---|---|
Host | https://www.google.com/ |
Connection | keep-alive |
Accept | text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 |
User-Agent | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 |
Referrer | https://www.google.com/ |
Accept-Encoding | gzip,deflate,sdch |
Accept-Language | en-US,en;q=0.8 |
经典的 Python 爬虫在使用 urllib 标准库时,都会发送如下的请求头:
属 性 | 内 容 |
---|---|
Accept-Encoding | identity |
User-Agent | Python-urllib/3.4 |
无论你在做什么项目,一定要记得把 User-Agent 属性设置成不容易引起怀疑的内容,不要用 Python-urllib/3.4。另外,如果你正在处理一个警觉性非常高的网站,就要注意那些经常用却很少检查的请求头,比如 Accept-Language 属 性,也许它正是那个网站判断你是个人类访问者的关键。
请求头会改变你观看网络世界的方式
假设你想为一个机器学习的研究项目写一个语言翻译机,却没有大量的翻译文本来 测试它的效果。很多大型网站都会为同样的内容提供不同的语言翻译,根据请求 头的参数响应网站不同的语言版本。因此,你只要简单地把请求头属性从 Accept- Language:en-US 修改成 Accept-Language:fr,就可以从网站上获得“Bonjour”(法语, 你好)这些数据来改善翻译机的翻译效果了(大型跨国企业通常都是好的采集对象)。
请求头还可以让网站改变内容的布局样式。例如,用移动设备浏览网站时,通常会看 到一个没有广告、Flash 以及其他干扰的简化的网站版本。因此,把你的请求头 User- Agent 改成下面这样,就可以看到一个更容易采集的网站了!
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53
12.2.2 处理 cookie
有一些浏览器插件可以为你显示访问网站和离开网站时 cookie 是如何设置的。EditThisCookie 就是我最喜欢的 Chrome 浏览器插件之一。
要获得 cookie 的更多信息,请查看 9.5 节,里面的示例代码介绍了使用 requests 模块处理 cookie 的过程。当然,因为 requests 模块不能执行 JavaScript,所以它不能处理很多新式的跟踪软件生成的 cookie,比如 Google Analytics,只有当客户端脚本执行后才设置 cookie (或者在用户浏览页面时基于网页事件产生 cookie,比如点击按钮)。为了处理这些动作, 你需要用 Selenium 和 PhantomJS 包(基本的安装和用法在第 10 章已经介绍过)。
你可以对任意网站(本例用的是 http://pythonscraping.com)调用 webdriver 的 get_cookie() 方法来查看 cookie, 你还可以调用 delete_cookie()、add_cookie() 和 delete_all_cookies() 方法来处理 cookie。另外,还可以保存 cookie 以备其他网络爬虫使用。
12.2.3 时间就是一切
有一些防护措施完备的网站可能会阻止你快速地提交表单,或者快速地与网站进行交互。 即使没有这些安全措施,用一个比普通人快很多的速度从一个网站下载大量信息也可能让自己被网站封杀。
因此,虽然多线程程序可能是一个快速加载页面的好办法——让你在一个线程中处理数据并在另一个线程中加载页面——但是这对编写好的爬虫来说依然是一个恐怖的策略。还是应该尽量保证一次加载页面加载且数据请求最小化。如果条件允许,尽量为每个页面访问增加一点儿时间间隔,即使你要增加一行代码:
time.sleep(3)
虽然网络数据采集经常会为了获取数据而破坏规则和冲破底线,但是合理控制速度是你不应该破坏的规则。这不仅是因为过度消耗别人的服务器资源会让你置身于非法境地,而且你这么做可能会把一个小型网站拖垮甚至下线。拖垮网站是一件不道德的事情:是彻头彻尾的错误。所以请控制你的采集速度!
12.3 常见表单安全措施
12.3.1 隐含输入字段值
在 HTML 表单中,“隐含”字段可以让字段的值对浏览器可见,但是对用户不可见(除非看网页源代码)。随着越来越多的网站开始用 cookie 存储状态变量来管理用户状态,在找到另一个最佳用途之前,隐含字段主要用于阻止爬虫自动提交表单。
用隐含字段阻止网络数据采集的方式主要有两种。
第一种是表单页面上的一个字段可以用服务器生成的随机变量表示。如果提交时这个值不在表单处理页面上,服务器就有理由认为这个提交不是从原始表单页面上提交的,而是由一个网络机器人直接提交到表单处理页面的。绕开这个问题的最佳方法就是,首先采集表单所在页面上生成的随机变量,然后再提交到表单处理页面。
第二种方式是“蜜罐”(honey pot)。如果表单里包含一个具有普通名称的隐含字段(设置蜜罐圈套),比如“用户名”(username)或“邮箱地址”(email address),设计不太好的网络机器人往往不管这个字段是不是对用户可见,直接填写这个字段并向服务器提交,这样就会中服务器的蜜罐圈套。服务器会把所有隐含字段的真实值(或者与表单提交页面的默认值不同的值)都忽略,而且填写隐含字段的访问用户也可能被网站封杀。
12.3.2 避免蜜罐
如果网络表单的一个字段通过 CSS 设置成对用户不可见,那么可以认为普通用户访问网站的时候不能填写这个字段,因为它没有显示在浏览器上。如果这个字段被填写了,就可能是机器人干的,因此这个提交 会失效。
这种手段不仅可以应用在网站的表单上,还可以应用在链接、图片、文件,以及一些可以被机器人读取,但普通用户在浏览器上却看不到的任何内容上面。访问者如果访问了网站
上的一个“隐含”内容,就会触发服务器脚本封杀这个用户的 IP 地址,把这个用户踢出网站,或者采取其他措施禁止这个用户接入网站。实际上,许多商业模式就是在干这些事情。
虽然你不太可能会去访问你找到的那些隐含链接,但是在提交前,记得确认一下那些已经在表单中、准备提交的隐含字段的值(或者让 Selenium 为你自动提交)。
12.4 问题检查表
如果你一直被网站封杀却找不到原因,那么这里有个检查列表,可以帮你诊断一下问题出在哪里。
• 首先,如果你从网络服务器收到的页面是空白的,缺少信息,或其遇到他不符合你预期的情况(或者不是你在浏览器上看到的内容),有可能是因为网站创建页面的 JavaScript 执行有问题。可以看看第 10 章内容。
• 如果你准备向网站提交表单或发出 POST 请求,记得检查一下页面的内容,看看你想提交的每个字段是不是都已经填好,而且格式也正确。用 Chrome 浏览器的网络面板(快捷键 F12 打开开发者控制台,然后点击“Network”即可看到)查看发送到网站的 POST 命令,确认你的每个参数都是正确的。
• 如果你已经登录网站却不能保持登录状态,或者网站上出现了其他的“登录状态”异常,请检查你的 cookie。确认在加载每个页面时 cookie 都被正确调用,而且你的 cookie 在 每次发起请求时都发送到了网站上。
• 如果你在客户端遇到了 HTTP 错误,尤其是 403 禁止访问错误,这可能说明网站已经把 你的 IP 当作机器人了,不再接受你的任何请求。你要么等待你的 IP 地址从网站黑名单里移除,要么就换个 IP 地址(可以去星巴克上网,或者看看第 14 章的内容)。如果你确定自己并没有被封杀,那么再检查下面的内容。
♦ 确认你的爬虫在网站上的速度不是特别快。快速采集是一种恶习,会对网管的服务 器造成沉重的负担,还会让你陷入违法境地,也是 IP 被网站列入黑名单的首要原因。
给你的爬虫增加延迟,让它们在夜深人静的时候运行。切记:匆匆忙忙写程序或收
集数据都是拙劣项目管理的表现;应该提前做好计划,避免临阵慌乱。
♦ 还有一件必须做的事情:修改你的请求头!有些网站会封杀任何声称自己是爬虫的
访问者。如果你不确定请求头的值怎样才算合适,就用你自己浏览器的请求头吧。
♦ 确认你没有点击或访问任何人类用户通常不能点击或接入的信息(更多信息请查阅
12.3.2 节)。
♦ 如果你用了一大堆复杂的手段才接入网站,考虑联系一下网管吧,告诉他们你的目的。
试试发邮件到 webmaster@< 域名 > 或 admin@< 域名 >,请求网管允许你使用爬虫采集数据。管理员也是人嘛!