13 scrapy框架之递归解析(手动发送请求)
递归爬取解析多页页面数据
- 需求:将糗事百科所有页码的作者和段子内容数据进行爬取切持久化存储(这里储存到文件当中)
- 需求分析:每一个页面对应一个url,则scrapy工程需要对每一个页码对应的url依次发起请求,然后通过对应的解析方法进行作者和段子内容的解析。
实现方案:
1.将每一个页码对应的url存放到爬虫文件的起始url列表(start_urls)中。(不推荐)
2.使用Request方法手动发起请求。(推荐)
代码展示:
爬虫文件:
1 # -*- coding: utf-8 -*- 2 import scrapy 3 from choutiDemo.items import ChoutidemoItem 4 5 6 class ChoutiSpider(scrapy.Spider): 7 name = 'chouti' 8 # allowed_domains = ['www.xxxx.html'] 9 start_urls = ['https://dig.chouti.com/r/scoff/hot/1'] 10 # 定义url 11 # 通用的url封装(每页的url) 12 url = "https://dig.chouti.com/r/scoff/hot/%d" 13 begin_url = 1 # 起始页码为1 14 15 def parse(self, response): 16 div_list = response.xpath('//div[@class="content-list"]/div') 17 for div in div_list: 18 # 1.获取解析到数据值,并封装到item对象中 19 title = div.xpath('./div[3]/div[1]/a/text()').extract_first() 20 author = div.xpath('./div[3]/div[2]/a[4]/b/text()').extract_first() 21 22 # 2.实例化一个item类型的对象,并将解析到数据封装到item对象当中 23 item = ChoutidemoItem() 24 item["title"] = title 25 item["author"] = author 26 27 # 3.使用yield将item对象交给管道进行持久化储存 28 yield item 29 30 # 爬取所有页码的数据 31 if self.begin_url<=3: # 页码的一个范围 32 # 封装成一个新的页面的url 33 self.begin_url +=1 34 new_url = format(self.url%self.begin_url) 35 # 手动发送请求,递归爬取数据:callback参数的值为回调函数(callback指定解析方法) 36 # (将url请求后,得到的相应数据继续进行parse解析),递归调用parse函数 37 yield scrapy.Request(url=new_url,callback=self.parse)
item.py文件 (定义属性)
import scrapy class ChoutidemoItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() author = scrapy.Field()
pipelines.py 文件(管道文件,进行持久化存储)
1 # 将提交过来的item数据,存储到文件中 2 class ChoutidemoPipeline(object): 3 fp = None 4 5 # 1.open_spider方法只会在开始爬虫的时候执行一次(只执行一次!!! 6 def open_spider(self,spider): 7 self.fp = open("./duanzi.txt","w",encoding="utf-8") 8 print("开始爬虫!!!") 9 10 # 2.因为process_item方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中 11 # 爬虫文件每提交一次item,该方法会被调用一次 12 # 方法里面的item就是爬虫文件给我提交的item 13 def process_item(self, item, spider): 14 self.fp.write(item['title']+":" + item["author"]+ "\n") 15 return item 16 17 # 3.结束爬虫的时候执行一次 18 def close_spider(self,spider): 19 self.fp.close() 20 print("结束爬虫!!!")
setting.py (配置文件,开启管道)
ITEM_PIPELINES = { 'choutiDemo.pipelines.ChoutidemoPipeline': 300, }