(python评论区教程)(python评论区教程)

环境准备:

  1. 使用pip安装lxml和scrapy
  2. scrapy startproject amazon_comment创建一个名为amazon_comment的scrapy爬虫项目

scrapy核心工作流程:

  1. scrapy.spiders.Spider中,有个变量start_urls,是数组类型,表示我们需要让爬虫从哪些链接开始爬取。Spider会以start_urls中的链接,生成一个含有默认回调函数parse的Request,然后使用该链接发出HTTP请求,获取到HTTP响应内容,封装成Response对象,然后把该Response对象作为参数传递给回调函数parse。Spider中最开始的Request是通过调用start_requests()方法来获取的,start_requests()方法是Spider默认实现好的,我们一般不用去实现这个方法。在start_requests()方法中,是通过读取start_urls中的链接,默认的以parse作为回调函数生成Request请求的。
  2. 当获取到Response对象之后,我们可以覆盖回调函数:parse方法,也可以在生成Request指定我们想要的任何回调函数。这样,Response就会作为参数传入我们指定的回调函数里面了(默认是parse方法)。然后,我们可以在我们设置的回调函数里面,从Response对象解析出返回的网页header内容,网页body内容。最常见的就是使用scrapy提供的scrapy.selector.Selector来从网页body中提取出我们想要的网页内容。我们设置的回调函数可以返回一个Item对象,或者是一个dict,或者是Request对象,或者是一个包括这三个东西的可迭代对象。在使用Selector提取网页内容时,最常见的就是使用xpath语法来定位和提取网页中我们想要的数据。
  3. 如果回调函数返回的是Request对象,那么这个Request对象之后又会经过Scrapy处理(发请求,获取Response,传递给回调函数处理)。
  4. 如果我们设置的回调函数返回的是Item对象,那么scrapy会把该Item传递给scrapy中我们定义好的 Item Pipeline处理,所以,我们一般都要实现ItemPipeline,最常见的是在Item Pipeline中把Item对象格式化成我们想要的格式,然后持久化到数据库中。

(python评论区教程)(python评论区教程)

当我们实现scrapy.spiders.Spider时:

如果是不需要登录,不需要设置header的,只通过一个url就能访问的网页,那么在scrapy.spiders的Spider类中,重写parse(response)方法即可。

如果是不需要登录,需要设置header的(一般设置User-Agent和Referer),通过url就能访问的网页,那么重写parse(response)方法,然后在scrapy.spiders的Spider类中,重写start_requests()方法,在该方法中返回一个设置了headers参数的scrapy.http.Request对象即可。该Request对象还可以设置callback,如果设置了callback,该start_requests方法返回该Request对象后,scrapy内部会根据该Request发出请求,获取scrapy.http.Response对象,然后把Response对象传递给该callback方法作参数,然后执行该callback方法;如果没有设置callback,那么scrapy内部会根据该Request发出请求,获取scrapy.http.Response对象,然后把Response对象传递给parse方法作参数,然后执行parse方法。

如果是需要登录,需要设置header的,通过url访问的网页,那么可以在start_urls中第一个元素设置为登录的url,然后在start_requests()方法中,返回一个设置了formdata参数的scrapy.FormRequest对象。该FormRequest是继承自scrapy.http.Request对象的,FormRequest没有设置额外必需的位置参数,提供了可选参数formdata,当formdata不为None时,method必为POST(FormRequest的__init__方法会自动设置)。FormRequest显然可以当做Request使用。所有Request的默认的回调函数是parse(response)方法,设置了另外的回调函数的话,该parse方法不会被调用。

scrapy核心方法:scrapy.spiders.Spider.start_requests():

上面提到,scrapy在开始工作时会以执行start_requests()方法,该方法中会以start_urls变量中的链接来创建Request,从而下载网页。我们来看一下start_requests()方法的默认实现。

该方法的默认实现为,

(python教程翁继星)(python教程翁继星)

(python评论区教程)(python评论区教程)

通常把该方法实现为一个生成器(包含yield的函数),因为我们会在start_urls中存储我们想爬取的url,对于start_urls中的每一个url的处理,该方法只会调用一次(并不是在该项目的整个爬取过程中只调用一次,而是对于每个url只调用一次),然后调用回调函数处理Response从而获取item。

所以如果我们重写了这个方法,那么我们一般也将它实现为生成器,即在yield中通过make_requests_from_url(url)方法返回默认的Request对象。例如,

(python评论区教程)(python评论区教程)

scrapy.spiders.Spider中该方法的默认实现会从start_urls中取url来生成scrapy.http.Request,我们在该方法中也可以不使用start_urls而是自己随意使用url生成Request返回。

(趣味学python)(python语言趣味教程)

Request的必备参数只有一个,如Request的构造方法为,

(python评论区教程)(python评论区教程)

Request的构造方法

FormRequest

在一个网页需要登录或者提交表单数据才能访问时,我们可以不使用默认的Request而是FormRequest。FormRequest从名字上就可以看出,就是为了在请求中模拟表单请求而存在的。

scrapy.FormRequest继承自Request,无额外的必备参数,可以设置formdata参数来使用POST提交数据。

如,

(python评论区教程)(python评论区教程)

scrapy核心方法:scrapy.spiders.Spider.parse(response):

parse方法是scrapy.http.Request中默认的回调函数,在Request中我们如果不显式声明回调函数的话,Request会默认把parse方法作为回调函数使用。

parse方法必须返回一个包含scrapy.http.Request对象、dict、project.items中定义的Item的可迭代的对象(一般实现为生成器,即在方法最后使用yield item或者yield Request)。

parse方法如果返回scrapy.http.Request对象,则scrapy内部还会通过该Request对象获取scrapy.http.Response,然后传递给该Request中的回调函数并调用该回调函数(默认是parse方法)。

parse方法中可以使用自定义的任何解析器来分析Response,获取item(一般是使用xpath,即scrapy.selector.Selector.xpath()方法,该方法还是返回一个Selector对象)。如

(python评论区教程)(python评论区教程)

parse方法中提取想要的数据:scrapy.selector.Selector和xpath:

在parse方法中,要从抓取的网页提取感兴趣的数据,需要使用到Selector和xpath。

Selector构造函数为:

Selector(response=None, text=None, type=None, namespaces=None, _root=None, _expr=None)

Selector常用方法为:

  1. extract():返回Selector对象的unicode字符串列表。
  2. extract_first():返回Selector对象匹配到的第一个元素。
  3. xpath():返回一个Selector对象

Selector和xpath使用示例:

  1. Selector(response).xpath('//span/text()').extract(): # 以列表方式返回所有span元素的文本内容。
  2. Selector(response).xpath('//div[@id]/a[1]/text()').extract(): # @表示选取属性,该句表示以列表形式返回所有具有id属性的div中第一个超链接的文本内容。或者使用Selector(response).xpath('//div[@id]/a/text()').extract_first()Selector(response).xpath('//div[@id and @class]/a/text()').extract(): # 多个条件用and连接
  3. Selector(response).xpath('//div[@id="images"]/a[1]/text()').extract(): # @表示选取属性,该句表示以列表形式返回所有id为images的div中第一个超链接的文本内容。
  4. Selector(response).xpath('//div[ul]/a/text()').extract(): # 以列表形式返回所有含有ul子元素的div中所有超链接的文本内容。
  5. Selector(response).xpath('//div[last()]/a/text()').extract(): # 以列表形式返回最后一个div中所有超链接的文本内容。
  6. Selector(response).xpath('//a[contains(@href, "image")]/@href').extract(): # 以列表形式返回所有的超链接中,其href属性包含"image"内容的那些超链接的链接内容。<a href="http://image1.html">超链接</a>这样的链接会被匹配上,因为href属性包含"image"内容。
  7. element_dom.xpath("//div[@class='item_list']//li/a/@href"): # 选取任意位置的class为item_list的div节点的全部子节点li【div后代节点,不管在div中任何位置】中a节点的href属性

xpath链式写法、条件嵌套和多条件查找:

xpath()完之后,仍然可以继续xpath:

(python评论区教程)(python评论区教程)

注意:xpath链式写法重复利用时,'//'前需要加上点'.'。如在某个xpath对象下继续使用xpath规则提取, 当提取某个对象下的所有某个对象所有tr标签:

(python评论区教程)(python评论区教程)

xpath多条件查找:

假设xml内容为下图,我们想要查找包含“data”节点并且“data”的type属性为"String"并且“data”节点的文本为“Alpha”的所有“cell”节点(即下图中的第一个data节点):

(python评论区教程)(python评论区教程)

满足需求的xpath为://cell[data[text()='Alpha'] and data[@type='String']] 或 //cell[data[text()='Alpha' and @type='String']]。//cell表示搜索所有的cell节点,中括号[]里面是条件,满足了中括号中所有条件的cell节点会被搜索出来,data[text()='Alpha' and @type='String']表示(节点文本="Alpha"且type="String")的子节点会被搜索出来。其中,中括号中的多个条件用and连接,相当于Python条件表达式中的and语法。

如果要在加一层结点的话,则中括号[]继续嵌套,想要查找子孙节点为data节点并且该data节点的type属性为"String"并且data节点的文本为“Alpha”的所有Row结点:

(python评论区教程)(python评论区教程)

满足条件的xpath为://row[cell/data[text()='Alpha'] and cell/data[@type='String']] 或 //row[cell/data[text()='Alpha' and @type='String']]

Selector().css()

与xpath类似,我们也可以在Selector上使用css()方法来查找元素。

css()方法:返回一个Selector对象,采用css语法来查找元素。

css()示例:

  1. Selector(response).css('title::text').extract() # 以列表方式返回所有title元素的文本内容。
  2. Selector(response).css('base::attr(href)').extract() # 以列表方式返回所有base元素的href属性内容。
  3. Selector(response).css('a[href*=image]::attr(href)').extract() # 以列表方式返回所有超链接中,href属性包含"image"的那些超链接的链接内容。
  4. Selector(response).css('a[href*=asks] .num::text').extract() # 以列表方式返回所有超链接中,href属性包含"asks"的那些超链接下,class为num的那些元素的文本内容。

(python评论区教程)(python评论区教程)

更多文章

喜欢的可以关注,赞赏多多支持一下!

声明:我要去上班所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,版权归原作者所有,原文出处。若您的权利被侵害,请联系删除。

本文标题:(python评论区教程)(python评论区教程)
本文链接:https://www.51qsb.cn/article/1847.html

(0)
打赏微信扫一扫微信扫一扫QQ扫一扫QQ扫一扫
上一篇2022-09-08
下一篇2022-09-08

你可能还想知道

发表回复

登录后才能评论