Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写!
高级网络爬虫技术:绕过 “403 Forbidden”,验证码等主要针对以下四种反爬技术:Useragent过滤;模糊的Javascript重定向;验证码;请求头一致性检查。
爬虫的完整代码可以在 github 上对应的仓库里找到。
简介(进群:943752371可以获取Python入门学习资料!)
Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写!
我从不把爬取网页当做是我的一个爱好或者其他什么东西,但是我确实用网络爬虫做过很多事情。因为我所处理的许多工作都要求我得到无法以其他方式获得的数据。我需要为 Intoli 做关于游戏数据的静态分析,所以我爬取了Google应用商店的数据来寻找最新被下载的APK。Pointy Ball插件需要聚合来自不同网站的梦幻足球(游戏)的预测数据,最简单的方式就是写一个爬虫。在我在考虑这个问题的之前,我大概已经写了大约 40~50 个爬虫了。我不太记得当时我对我家人撒谎说我已经抓取了多少 TB 的数据….,但是我确实很接近那个数字了。
我尝试使用 xray/cheerio、nokogiri 和一些其他的工具。但我总是会回到我个人的最爱 Scrapy。在我看来,Scrapy是一个出色的软件。我对这款软件毫无保留的赞美是有原因的,它的用法非常符合直觉,学习曲线也很平缓。
你可以阅读Scrapy的教程,在几分钟内就可以让你的第一个爬虫运行起来。然后,当你需要做一些更复杂的事情的时候,你就会发现,有一个内置的、有良好文档说明的方式来做到这一点。这个框架有大量的内置功能,但是它的结构使得在你用到这些功能之前,不会妨碍到你。当你最终确实需要某些默认不存在的功能的时候,比如说,因为访问了太多的 URL 链接以至于无法存储到内存中,需要一个用于去重的 bloom filter(布隆过滤器),那么通常来说这就和继承其中的组件,然后做一点小改动一样简单。一切都感觉如此简单,而且scrapy是我书中一个关于良好软件设计的例子。
我很久以前就想写一个高级爬虫教程了。这给我一个机会来展示scrapy的可扩展性,同时解决实践中出现的现实问题。尽管我很想做这件事,但是我还是无法摆脱这样一个事实:因为发布一些可能导致他人服务器由于大量的机器人流量受到损害的文章,就像是一个十足的坏蛋。
只要遵循几个基本的规则,我就可以在爬取那些有反爬虫策略的网站的时候安心地睡个好觉。换句话说,我让我的请求频率和手动浏览的访问频率相当,并且我不会对数据做任何令人反感的事情。这样就使得运行爬虫收集数据基本上和以其他主要的手动收集数据的方法无法区分。但即使我遵守了这些规则,我仍感觉为人们实际想要爬取的网站写一个教程有很大的难度。
直到我遇到一个叫做Zipru的BT下载网站,这件事情仍然只是我脑海里一个模糊的想法。这个网站有多个机制需要高级爬取技术来绕过,但是它的 robots.txt 文件却允许爬虫爬取。此外,其实我们不必去爬取它。因为它有开放的API,同样可以得到全部数据。如果你对于获得torrent的数据感兴趣,那就只需要使用这个API,这很方便。
在本文的剩余部分,我将带领你写一个爬虫,处理验证码和解决我们在Zipru网站遇到的各种不同的挑战。样例代码无法被正常运行因为 Zipru 不是一个真实存在的网站,但是爬虫所使用的技术会被广泛应用于现实世界中的爬取中。因此这个代码在另一个意义上来说又是完整的。我们将假设你已经对 Python 有了基本的了解,但是我仍会尽力让那些对于 Scrapy 一无所知的人看懂这篇文章。如果你觉得进度太快,那么花几分钟的时间阅读一下Scrapy官网教程吧。
建立工程项目
我们会在 virtualenv 中建立我们的项目,这可以让我们封装一下依赖关系。首先我们在~/scrapers/zipru中创建一个virtualenv ,并且安装scrapy包。
Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写!
你运行的终端将被配置为使用本地的virtualenv。如果你打开另一个终端,那么你就需要再次运行. ~/scrapers/zipru/env/bin/active 命令 (否则你有可能得到命令或者模块无法找到的错误消息)。
现在你可以通过运行下面的命令来创建一个新的项目框架:
Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写!
这样就会创建下面的目录结构。
Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写!
大多数默认情况下产生的这些文件实际上不会被用到,它们只是建议以一种合理的方式来构建我们的代码。从现在开始,你应该把 ~/scrapers/zipru/zipru_scraper 当做这个项目的根目录。这里是任何scrapy命令运行的目录,同时也是所有相对路径的根。
添加一个基本的爬虫功能
现在我们需要添加一个Spieder类来让我们的scrapy真正地做一些事情。Spider类是scrapy爬虫用来解析文本,爬取新的url链接或是提取数据的一个类。我们非常依赖于默认Spider类的实现,以最大限度地减少我们必须要编写的代码量。这里要做的事情看起来有点自动化,但假如你看过文档,事情会变得更加简单。
首先,在zipru_scraper/spiders/目录下创建一个文件,命名为 zipru_spider.py ,输入下面内容。
Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写!
你可以在上面的网页中看到许多指向其他页面的连接。我们想让我们的爬虫跟踪这些链接,并且解析他们的内容。为了完成这个任务,我们首先需要识别出这些链接并且弄清楚他们指向的位置。
在这个阶段,DOM检查器将起到很大的助力。如果你右击其中的一个页面链接,在DOM检查器里面查看它,然后你就会看到指向其他页面的链接看起来像是这样的:
Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写!
接下来我们需要为这些链接构造一个选择器表达式。有几种类型似乎用css或者xpath选择器进行搜索更适合,所以我通常倾向于灵活地混合使用这几种选择器。我强烈推荐学习xpath,但是不幸的是,它有点超出了本教程的范围。我个人认为xpath对于网络爬虫,web UI 测试,甚至一般的web开发来说都是不可或缺的。我接下来仍然会使用css选择器,因为它对于大多数人来说可能比较熟悉。
要选择这些页面链接,我们可以把 a[title ~= page] 作为一个 css 选择器,来查找标题中有 “page” 字符的 标签。如果你在 DOM 检查器中按 ctrl-f,那么你就会发现你也可以使用这个css表达式作为一条查找语句(也可以使用xpath)。这样我们就可以循环查看所有的匹配项了。这是一个很棒的方法,可以用来检查一个表达式是否有效,并且表达式足够明确不会在不小心中匹配到其他的标签。我们的页面链接选择器同时满足了这两个条件。
为了讲解我们的爬虫是怎样发现其他页面的,我们在 ZipruSpider 类中添加一个 parse(response) 方法,就像下面这样:
Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写!
当我们开始爬取的时候,我们添加到 start_urls 中的链接将会被自动获取到,响应内容会被传递到 parse(response) 方法中。之后我们的代码就会找到所有指向其他页面的链接,并且产生新的请求对象,这些请求对象将使用同一个 parse(response) 作为回调函数。这些请求将被转化成响应对象,只要 url 仍然产生,响应就会持续地返回到 parse(response)函数(感谢去重器)。
我们的爬虫已经可以找到了页面中列出的所有不同的页面,并且对它们发出了请求,但我们仍然需要提取一些对爬虫来说有用的数据。torrent 列表位于
| 标签,分别与 “类别”,“文件”,“添加时间”,“文件大小”,“保种的人”,“下载文件的人”,“文件描述”,和“上传者”相对应。在代码中查看其它的细节可能是最简单的方法,下面是我们修改后的 parse(response) 方法: Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写! 我们的 parse(response) 方法现在能够返回字典类型的数据,并且根据它们的类型自动区分请求。每个字典都会被解释为一项,并且作为爬虫数据输出的一部分。 如果我们只是爬取大多数常见的网站,那我们已经完成了。我们只需要使用下面的命令来运行: scrapy crawl zipru -o torrents.jl 几分钟之后我们本应该得到一个 [JSON Lines] 格式 torrents.jl 文件,里面有我们所有的torrent 数据。取而代之的是我们得到下面的错误信息(和一大堆其他的东西): Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写! 我好气啊!我们现在必须变得更聪明来获得我们完全可以从公共API得到的数据,因为上面的代码永远都无法爬取到那些数据。 简单的问题 我们的第一个请求返回了一个 403 响应,所以这个url被爬虫忽略掉了,然后一切都关闭了,因为我们只给爬虫提供了一个 url 链接。同样的请求在网页浏览器里运行正常,即使是在没有会话(session)历史的隐匿模式也可以,所以这一定是由于两者请求头信息的差异造成的。我们可以使用 tcpdump 来比较这两个请求的头信息,但其实有个常见错误,所以我们应该首先检查: user agent 。 Scrapy 默认把 user-agent 设置为 “Scrapy/1.3.3 (+http://scrapy.org)“,一些服务器可能会屏蔽这样的请求,甚至使用白名单只允许少量的user agent 通过。你可以在线查看 最常见的 user agent ,使用其中任何一个通常就足以绕过基本反爬虫策略。选择一个你最喜欢的 User-agent ,然后打开 zipru_scraper/settings.py ,替换 User agent Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写! 使用下面内容替换 USER_AGENT : USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36' 你可能注意到了,默认的scrapy设置中有一些令爬虫蒙羞的事。关于这个问题的观点众说纷纭,但是我个人认为假如你想让爬虫表现的像是一个人在使用普通的网页浏览器,那么你就应该把你的爬虫设置地像普通的网络浏览器那样。所以让我们一起添加下面的设置来降低一下爬虫响应速度: Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写! 通过 AutoThrottle 扩展 ,上面的设置会创建一个稍微真实一点的浏览模式。我们的爬虫在默认情况下会遵守 robots.txt,所以现在我们的行为非常检点。 现在使用 scrapy crawl zipru -o torrents.jl 命令再次运行爬虫,应该会产生下面的输出: Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写! 这是一个巨大的进步!我们获得了两个 200 状态码和一个 302状态码,下载中间件知道如何处理 302 状态码。不幸的是,这个 302 将我们的请求重定向到了一个看起来不太吉利的页面 threat_defense.php。不出所料,爬虫没有发现任何有用的东西,然后爬虫就停止运行了。 注: 假如网站检测到你的爬虫,那么网站就会把你的请求重定向到 threat_defense.php 页面,使你的爬虫失效,用来防止频繁的爬虫请求影响了网站正常用户的使用。 下载中间件 在我们深入研究我们目前所面临的更复杂的问题之前,先了解一下请求和响应在爬虫中是怎样被处理的,将会很有帮助。当我们创建了我们基本的爬虫,我们生成了一个 scrapy.Request 对象,然后这些请求会以某种方法转化为与服务器的响应相对应的 scrapy.Response对象。这里的 “某种方法” 很大一部分是来自于下载中间件。 下载中间件继承自 scrapy.downloadermiddlewares.DownloaderMiddleware 类并且实现了 process_request(request, spider) 和 process_response(request, response, spider) 方法。你大概可以从他们的名字中猜到他们是做什么的。实际上这里有一大堆的默认开启的中间件。下面是标准的中间件配置(你当然可以禁用、添加或是重新设置这些选项): Python爬虫?今天教大家玩更厉害的,反爬虫操作!零基础都能写! 当一个请求到达服务器时,他们会通过每个这些中间件的 process_request(request, spider) 方法。 这是按照数字顺序发生的,RobotsTxtMiddleware 中间件首先产生请求,并且 HttpCacheMiddleware 中间件最后产生请求。一旦接收到一个响应,它就会通过任何已启用的中间件的 process_response(request,response,spider) 方法来返回响应。这次是以相反的顺序发生的,所以数字越高越先发送到服务器,数字越低越先被爬虫获取到。
Python相关栏目本月热门文章
热门相关搜索
路由器设置
木托盘
宝塔面板
儿童python教程
心情低落
朋友圈
vim
双一流学科
专升本
我的学校
日记学校
西点培训学校
汽修学校
情书
化妆学校
塔沟武校
异形模板
西南大学排名
最精辟人生短句
6步教你追回被骗的钱
南昌大学排名
清朝十二帝
北京印刷学院排名
北方工业大学排名
北京航空航天大学排名
首都经济贸易大学排名
中国传媒大学排名
首都师范大学排名
中国地质大学(北京)排名
北京信息科技大学排名
中央民族大学排名
北京舞蹈学院排名
北京电影学院排名
中国戏曲学院排名
河北政法职业学院排名
河北经贸大学排名
天津中德应用技术大学排名
天津医学高等专科学校排名
天津美术学院排名
天津音乐学院排名
天津工业大学排名
北京工业大学耿丹学院排名
北京警察学院排名
天津科技大学排名
北京邮电大学(宏福校区)排名
北京网络职业学院排名
北京大学医学部排名
河北科技大学排名
河北地质大学排名
河北体育学院排名
|



