Python爬虫突破封禁的6种常见方法

在互联网上进行自动数据采集(抓取)这件事和互联网存在的时间差不多一样长。今天大众好像更倾向于用“网络数据采集”,有时会把网络数据采集程序称为网络机器人(bots)。最常用的方法是写一个自动化程序向网络服务器请求数据(通常是用HTML表单或其他网页文件),然后对数据进行解析,提取需要的信息。

本文假定读者已经了解如何用代码来抓取一个远程的URL,并具备表单如何提交及JavaScript在浏览器如何运行的机制。想更多了解网络数据采集基础知识,可以参考文后的资料。

在采集网站的时会遇到一些比数据显示在浏览器上却抓取不出来更令人沮丧的事情。也许是向服务器提交自认为已经处理得很好的表单却被拒绝,也许是自己的IP地址不知道什么原因直接被网站封杀,无法继续访问。

图片2

经典的Python爬虫在使用urllib标准库时,都会发送如下的请求头:

图片4

程序输出结果中的请求头应该和程序中设置的headers是一样的。

虽然网站可能会对HTTP请求头的每个属性进行“是否具有人性”的检查,但是我发现通常真正重要的参数就是User-Agent。无论做什么项目,一定要记得把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 712 like Mac OS X) App leWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53

2. 设置cookie的学问

虽然cookie是一把双刃剑,但正确地处理cookie可以避免许多采集问题。网站会用cookie跟踪你的访问过程,如果发现了爬虫异常行为就会中断你的访问,比如特别快速地填写表单,或者浏览大量页面。虽然这些行为可以通过关闭并重新连接或者改变IP地址来伪装,但是如果cookie暴露了你的身份,再多努力也是白费。

在采集一些网站时cookie是不可或缺的。要在一个网站上持续保持登录状态,需要在多个页面中保存一个cookie。有些网站不要求在每次登录时都获得一个新cookie,只要保存一个旧的“已登录”的cookie就可以访问。

如果你在采集一个或者几个目标网站,建议你检查这些网站生成的cookie,然后想想哪一个cookie是爬虫需要处理的。有一些浏览器插件可以为你显示访问网站和离开网站时cookie是如何设置的。EditThisCookie(http://www.editthiscookie.com/)是我最喜欢的Chrome浏览器插件之一。

因为requests模块不能执行JavaScript,所以它不能处理很多新式的跟踪软件生成的cookie,比如GoogleAnalytics,只有当客户端脚本执行后才设置cookie(或者在用户浏览页面时基于网页事件产生cookie,比如点击按钮)。要处理这些动作,需要用Selenium和PhantomJS包。

Selenium与PhantomJS 
Selenium(http://www.seleniumhq.org/)是一个强大的网络数据采集工具,最初是为网站自动化测试而开发的。近几年,它还被广泛用于获取精确的网站快照,因为它们可以直接运行在浏览器上。Selenium可以让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。 
Selenium自己不带浏览器,它需要与第三方浏览器结合在一起使用。例如,如果你在Firefox上运行Selenium,可以直接看到Firefox窗口被打开,进入网站,然后执行你在代码中设置的动作。虽然这样可以看得更清楚,但是我更喜欢让程序在后台运行,所以我PhantomJS(http://phantomjs.org/download.html)代替真实的浏览器。 
PhantomJS是一个“无头”(headless)浏览器。它会把网站加载到内存并执行页面上的JavaScript,但不会向用户展示网页的图形界面。将Selenium和PhantomJS结合在一起,就可以运行一个非常强大的网络爬虫了,可以处理cookie、JavaScrip、header,以及任何你需要做的事情。 
可以从PyPI网站(https://pypi.python.org/simple/selenium/)下载Selenium库,也可以用第三方管理器(像pip)用命令行安装。

你可以对任意网站(本例用的是http://pythonscraping.com)调用webdriver的get_cookie()方法来查看cookie:

图片6

还可以调用deletecookie()、addcookie()和deleteallcookies()方法来处理cookie。另外,还可以保存cookie以备其他网络爬虫使用。下面的例子演示了如何把这些函数组合在一起:

图片8

Facebook登录页面上的隐含字段

用隐含字段阻止网络数据采集的方式主要有两种。第一种是表单页面上的一个字段可以用服务器生成的随机变量表示。如果提交时这个值不在表单处理页面上,服务器就有理由认为这个提交不是从原始表单页面上提交的,而是由一个网络机器人直接提交到表单处理页面的。绕开这个问题的最佳方法就是,首先采集表单所在页面上生成的随机变量,然后再提交到表单处理页面。

第二种方式是“蜜罐”(honey pot)。如果表单里包含一个具有普通名称的隐含字段(设置蜜罐圈套),比如“用户名”(username)或“邮箱地址”(email address),设计不太好的网络机器人往往不管这个字段是不是对用户可见,直接填写这个字段并向服务器提交,这样就会中服务器的蜜罐圈套。服务器会把所有隐含字段的真实值(或者与表单提交页面的默认值不同的值)都忽略,而且填写隐含字段的访问用户也可能被网站封杀。

总之,有时检查表单所在的页面十分必要,看看有没有遗漏或弄错一些服务器预先设定好的隐含字段(蜜罐圈套)。如果你看到一些隐含字段,通常带有较大的随机字符串变量,那么很可能网络服务器会在表单提交的时候检查它们。另外,还有其他一些检查,用来保证这些当前生成的表单变量只被使用一次或是最近生成的(这样可以避免变量被简单地存储到一个程序中反复使用)。

5. 爬虫通常如何避开蜜罐

虽然在进行网络数据采集时用CSS属性区分有用信息和无用信息会很容易(比如,通过读取id和class标签获取信息),但这么做有时也会出问题。如果网络表单的一个字段通过CSS设置成对用户不可见,那么可以认为普通用户访问网站的时候不能填写这个字段,因为它没有显示在浏览器上。如果这个字段被填写了,就可能是机器人干的,因此这个提交会失效。

这种手段不仅可以应用在网站的表单上,还可以应用在链接、图片、文件,以及一些可以被机器人读取,但普通用户在浏览器上却看不到的任何内容上面。访问者如果访问了网站上的一个“隐含”内容,就会触发服务器脚本封杀这个用户的IP地址,把这个用户踢出网站,或者采取其他措施禁止这个用户接入网站。实际上,许多商业模式就是在干这些事情。

下面的例子所用的网页在http://pythonscraping.com/pages/itsatrap.html。这个页面包含了两个链接,一个通过CSS隐含了,另一个是可见的。另外,页面上还包括两个隐含字段:

图片9

这三个元素通过三种不同的方式对用户隐藏:

  • 第一个链接是通过简单的CSS属性设置display:none进行隐藏
  • 电话号码字段name=”phone”是一个隐含的输入字段
  • 邮箱地址字段name=”email”是将元素向右移动50 000像素(应该会超出电脑显示器的边界)并隐藏滚动条

因为Selenium可以获取访问页面的内容,所以它可以区分页面上的可见元素与隐含元素。通过is_displayed()可以判断元素在页面上是否可见。

来源:offbye

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2016年7月15日
下一篇 2016年7月16日

相关推荐