当前位置: 首页 > 科技观察

pyspider爬虫教程(二):AJAX和HTTP

时间:2023-03-12 20:49:33 科技观察

在上一篇教程《pyspider 爬虫教程 (1):HTML 和 CSS 选择》中,我们使用self.crawlAPI抓取豆瓣电影的HTML内容,并使用CSS选择器解析部分内容。然而,当今的网站使用AJAX等技术来避免在您与服务器交互时重新加载整个页面。但是,这些交互手段让爬取变得有些困难:你会发现这些网页被爬取后和浏览器中的不一样。您需要的信息不在返回的HTML代码中。在本教程中,我们将讨论这些技术和抓取它们的方法。AJAXAJAX是AsynchronousJavaScriptandXML(异步JavaScript和XML)的缩写。AJAX是利用原有的Web标准组件,在不重新加载整个页面的情况下,实现与服务器的数据交互。例如,在新浪微博中,您可以在不重新加载或打开新页面的情况下展开微博评论。但是这些内容并不是一开始就在页面上的(所以页面太大了),而是在你点击的时候加载的。这就导致当你爬取这个页面时,你无法获取到这些评论信息(因为你还没有“展开”)。AJAX的一个常见用途是使用AJAX加载JSON数据,然后在浏览器端进行渲染。如果能直接抓取JSON数据,会比HTML更容易解析。当网站使用AJAX时,除了pyspider抓取的页面和浏览器看到的不一样。当您在浏览器中打开这样的页面,或点击“展开”时,您经常会看到“正在加载”或类似的图标/动画。例如,当你尝试爬取:http://movie.douban.com/explore时,你会发现电影正在“loading...”中寻找真正的请求。由于AJAX实际上是通过HTTP传输数据的,我们可以通过Chrome开发者工具找到真实的请求,直接发起对真实请求的抓取来获取数据。打开一个新窗口并按Ctrl+Shift+I(在Mac上为Cmd+Opt+I)打开开发者工具。切换到网络(Netwotk面板),在一个窗口中打开http://movie.douban.com/explore。在页面加载期间,您将在面板中看到所有资源请求。AJAX一般通过XMLHttpRequest对象接口发送请求,一般简称为XHR。单击Network面板上的漏斗形过滤器按钮以过滤掉XHR请求。一一查看每个请求,通过访问路径找到包含信息的请求并预览:http://movie.douban.com/j/searchX61Xsubjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0在豆瓣的例子中,XHR请求不多,可以一一查看确认。但是,当XHR请求较多时,可能需要结合触发动作的时间、请求的路径等信息,帮助在大量请求中找到包含信息的关键请求。这个需要有爬虫或者前端相关经验。因此,有一点我一直在强调。学习爬虫最好的方法是:学习写网站。现在你可以在新窗口打开http://movie.douban.com/j/searchX67Xsubjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0,你会看到电影包含数据的JSON原始数据。推荐安装JSONView(Firfox版)插件,可以看到更好看的JSON格式,展开和收起列等功能。然后,我们编写一个脚本,根据JSON数据提取电影名称和评分:classHandler(BaseHandler):defon_start(self):self.crawl('http://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0',callback=self.json_parser)defjson_parser(self,response):return[{"title":x['title'],"rate":x['rate'],"url":x['url']}forxinresponse.json['subjects']]可以用response.json把结果转成python的dict对象,可以找到在http://demo.pyspider.org/debug/tutorial_douban_explore中获取完整代码,并进行调试。还有一个使用PhantomJS呈现的脚本的提取版本,将在下一个教程中介绍。HTTPHTTP是一种用于传输Web内容的协议。在之前的教程中,我们已经通过self.crawl接口提交了抓取的url。这些提取通过HTTP协议传输。在爬取过程中,可能会遇到403Forbidden等情况,或者需要登录,这时候就需要使用正确的HTTP参数进行爬取。一个典型的HTTP请求包如下。这个请求发送到http://example.com/:GET/HTTP/1.1Host:example.comConnection:keep-aliveCache-Control:max-age=0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8User-Agent:Mozilla/5.0(Macintosh;IntelMacOSX10_10_1)AppleWebKit/537.36(KHTML,likeGecko)Chrome/40.0.2214.45Safari/537.36Referer:http://en.wikipedia.org/wiki/Example.comAccept-Encoding:gzip,deflate,sdchAccept-Language:zh-CN,zh;q=0.8If-None-Match:"359670651"If-Modified-Since:Fri,09Aug201323:54:35GMT请求的第一行包含HTTP协议的方法、路径和版本信息。剩下的几行称为headers,以key:value的形式呈现。如果是POST请求,请求末尾可能会有body内容。你可以通过之前使用的ChromeDeveloperTools工具查看这些信息:在大多数情况下,你总是可以用正确的方法、路径、headers和body抓取你需要的信息。HTTP方法HTTP方法告诉服务器如何处理URL资源。比如打开一个URL时使用GET方式,提交数据时一般使用POST方式。TODO:这里需要示例HTTPHeadersHTTPHeaders是请求带来的参数列表,你可以在这里找到完整的常用Headers列表。一些常见的需要注意的是:User-AgentUA是一个字符串,用于标识您正在使用的浏览器或爬虫。pyspider使用的默认UA是pyspider/VERSION(+http://pyspider.org/)。网站常用这个字符串来区分用户的操作系统和浏览器,判断对方是否是爬虫。所以在爬取的时候,UA往往是伪装的。在pyspider中,可以通过self.crawl(URL,headers={'User-Agent':'pyspider'}),或者crawl_config={'headers':{'User-Agent':'xxxx'}}来指定脚本级别的UA。详情请查看API文档。RefererReferer用于告诉服务器您上次访问的网页是什么。常用于防盗链,抓图时可能会用到。X-Requested-With是使用XHR发送AJAX请求时会包含的一个header,常用于判断是否为AJAX请求。比如北邮论坛,需要:defon_start(self):self.crawl('http://bbs.byr.cn/board/Python',headers={'X-Requested-With':'XMLHttpRequest'},callback=self.index_page)和headers={'X-Requested-With':'XMLHttpRequest'}来抓取内容。HTTPCookie虽然Cookie只是HTTPHeaders中的一种,但是因为它非常重要,所以还是先说说吧。HTTP请求使用Cookie来区分和跟踪用户身份。当您登录网站时,您通过写入Cookie字段来记录登录状态。当遇到需要登录的网站时,需要通过设置cookie参数来请求需要登录的内容。Cookies可以通过开发者工具的请求面板,或者资源面板获取。在pyspider中也可以使用response.cookies获取返回的cookie,使用self.crawl(URL,cookie={'key':'value'})设置请求的cookie参数。