概念和方式:
深度爬取:爬取的数据没有在同一张页面中(首页数据+详情页数据)
在scrapy中如果没有请求传参,我们无法持久化存储数据
实现方式:
- (url,callback,meta)
meta是一个字典,可以将meta传递给callback
- callback取出meta:
re['item']
例程:
爬取某电影网的电影名称和详情页的电影介绍
这个网站首页和详情介绍不在同一页面,利用requests很容易爬取,但用scrapy必须要用到深度爬取
创建一个工程moviePro:
- scrapy startproject moviePro
- cd moviePro
- scrapy genspider movie www.xxx.com
- 修改配置文件
我们先来取出电影名称和详情页URL:
import scrapy class MovieSpider): name = 'movie' # allowed_domains = ['www.xxx.com'] start_urls = [''] def parse(self, response): li_list = re('/html/body/div[1]/div/div/div/div[2]/ul/li') for li in li_list: # 获取电影名称 title = li.xpath('./div/a/@title').extract_first() # 详情页URL detail_url = '; + li.xpath('./div/a/@href').extract_first() print(title, detail_url)
运行一下:scrapy crawl movie
上节课我们讲了如果对新网站进行手动爬取:
那我们就可以对该电影网进行详情页的爬取:
yield (url=detail_url,callback=)
但我们遇到一个问题:callback=?,这里肯定不能写。我们可以再写个函数进行详情页的数据解析:
# yield (url=detail_url, callback=parse_detail) # 被作用于解析详情页的数据 def parse_detail(self, response): desc = re('/html/body/div[1]/div/div/div/div[2]/p[5]/span[3]').extract_first() ... yield ...
先别着急省略的代码。上面我们获取了电影名称和详情页数据,我们需要管道做持久化存储的话,需要定义item
i文件:
import scrapy class MovieproItem): # define the fields for your item here like: # name = () title = () desc = ()
那我们就把item写进代码中:
def parse(self, response): li_list = re('/html/body/div[1]/div/div/div/div[2]/ul/li') for li in li_list: # 获取电影名称 title = li.xpath('./div/a/@title').extract_first() detail_url = '; + li.xpath('./div/a/@href').extract_first() item = MovieproItem() item['title'] = title yield (url=detail_url, callback=_detail) # 被作用于解析详情页的数据 def parse_detail(self, response): desc = re('/html/body/div[1]/div/div/div/div[2]/p[5]/span[3]').extract_first() item['desc'] = desc
但是,这样的话肯定是报错的。因为parse_detail函数中并没有item,这时候,我们就需要用到请求传参:
def parse(self, response): li_list = re('/html/body/div[1]/div/div/div/div[2]/ul/li') for li in li_list: # 获取电影名称 title = li.xpath('./div/a/@title').extract_first() detail_url = '; + li.xpath('./div/a/@href').extract_first() item = MovieproItem() item['title'] = title # meta的作用:可以将mate字典传递给callback yield (url=detail_url, callback=_detail, meta={'item': item}) # 被作用于解析详情页的数据 def parse_detail(self, response): # 接收传递过来的mate item = re['item'] desc = re('/html/body/div[1]/div/div/div/div[2]/p[5]/span[3]').extract_first() item['desc'] = desc # 传递给管道 yield item
管道文件中打印下:
class MovieproPipeline: def process_item(self, item, spider): print(item) return item
我们来运行一下吧:
这样就爬取到了数据!
关注Python涛哥!学习更多Python知识!