scrapy分页抓取网页(crawlspiderrules有点疑问总结:1、rules里的Rule规则运行)
优采云 发布时间: 2021-10-19 17:01scrapy分页抓取网页(crawlspiderrules有点疑问总结:1、rules里的Rule规则运行)
最近在学习爬虫,对爬虫规则的运行机制有些疑惑,于是自己研究了一下,总结出以下几点:
1、规则中的规则是按顺序运行的,从上到下执行;
2、 获取request url是Rule定位的容器,a标签中的所有href链接,比如使用xpath定位
规则 = (
规则(LinkExtractor(restrict_xpaths=("//div/ul")),callback='parse_item'),
)
然后会获取ul容器下a标签的所有链接,服务器会自动发送请求,无需手动发送请求;
3、 响应页面就是Rule请求的链接的页面内容,也就是你在容器ul中定位a标签所在的链接,然后点击链接查看页面内容,在回调函数中提取数据。从这个页面中提取,parse_item(self,response),这个函数的响应对象就是这个页面的内容,不要搞错对象;
4、follow,这个参数开始让我有点晕。跟随意味着跟进。如果follow=True,那么在你得到的响应页面中,会获取所有符合规则的href链接 会自动跟进,进入获取的链接响应页面,在这个页面再次匹配规则规则,看是否有是任何匹配,如果匹配,则继续跟踪,直到匹配规则失败。例如:
规则 = (
规则(LinkExtractor(restrict_xpaths=(“//div/ul”)),follow=True),
)
所以首先规则会获取当前页面上所有符合规则规则的链接,当前页面为start_urls页面,例如获取的链接为
教科书
会继续进入href链接的页面,然后继续匹配Rule规则,看看有没有匹配的链接,相当于在响应页面的元素中找到符合规则的a标签url ,然后点击这个url,然后在这个页面的元素中查找是否有符合Rule规则的href链接,依此类推,直到找不到符合Rule规则的href链接;
5、如果Rule中有callback="parse_item",follow=True,那么情况会更复杂。你可以想象得到一个响应符合Rule规则的页面的链接,然后调用函数,跳转到这个页面。按照其他目标链接,然后调用该函数。最好使用xpath定位。如果使用allow=(r'')正则表达式匹配,会比较混乱。在适当的情况下也会用到,不过比较少嘛,大家可以自己测试体验一下。
6、 翻页,翻页有两种情况
第一种情况(start_url的响应页面底部有翻页链接):
在规则中定义两个Rule规则,一个是获取响应页面规则,一个是获取翻页链接规则,翻页规则遵循响应页面规则,顺序不能错,如下:
规则 = (
规则(LinkExtractor(allow=r'/web/site0/tab5240/info\d+\.htm'), callback='parse_item'),
规则(LinkExtractor(allow=r'\d\.htm'),follow=True),
)
第二种情况(start_url的响应页面底部没有翻页链接,只有输入a标签链接才有翻页链接):
在这种情况下,您无法在规则中定义翻页规则,因为即使您定义了翻页规则,也找不到它们。因为规则中的所有规则,第一次得到响应页面是start_url地址对应的内容。如果该页面没有规则规则,则不会被发现。这里就不多说了,直接上源码吧!
class TestSpider(CrawlSpider):
name = 'test'
allowed_domains = ['dangdang.com']
start_urls = ['http://book.dangdang.com/']
rules = (
Rule(LinkExtractor(restrict_xpaths=("//div[@class='conflq_body']/div[@name='m403752_pid5438_t10274']//div/dl[@ddt-area='5358']/dd")), callback='parse_item'),
)
def parse_item(self, response):
item={}
item['cate_0']=''
item['cate_1'] = ''
item['cate_2'] = ''
item['cate_3'] = ''
breadcrum=response.xpath("//div[@class='crumbs_fb_left']/div[@class='select_frame']/a[@name='breadcrumb-category']/text()").getall()
for i in range(len(breadcrum)):
item['cate_{}'.format(i)]=breadcrum[i]
book_li=response.xpath("//div[@id='search_nature_rg']/ul/li")
for li in book_li:
item['book_title']=li.xpath(".//p[@class='name']/a/@title").get()
item['book_price']=li.xpath(".//p[@class='price']/span/text()").get()
item['book_url']=li.xpath(".//p[@class='name']/a/@href").get()
book_search=li.xpath(".//p[@class='search_book_author']/span")
item['book_author']=book_search[0].xpath(".//a/@title").get()
item['public_date']=book_search[1].xpath(".//text()").get()
item['public_date']=re.sub("/",'',item['public_date']) if item['public_date'] else None
item['public_company']=book_search[2].xpath(".//a/@title").get()
yield item
next_page_url=response.xpath("//div[@class='paging']//li[@class='next']/a/@href").get()
next_page="http://category.dangdang.com"+next_page_url
yield scrapy.Request(next_page,callback=self.parse_item)
在这种情况下,必须在函数中进行翻页。parse_item() 函数的最后三行是翻页语句!我可以自己测试一下。不知道有没有其他方法可以做规则。反正我现在还没找到。如果有人知道,我可以告诉!
以上是我个人的看法,如有错误或遗漏,敬请指出!