Python 全栈工程师核心面试 300 问深入解析(2020 版)----全文预览
Python 全栈工程师核心面试 300 问深入解析(2020 版)----欢迎订阅
初学scrapy可能会有点蒙圈,今天和大家分享下scrapy中Request方法中meta参数的用法 :
- 我们要知道meta参数对应的值必须是一个字典
- 它的主要作用是用来传递数据的
- meta是通过Request产生时传进去,
- 通过Response对象中取出来
先看一个简单的例子
然后查看两个爬虫实例,进一步理解meta参数的使用:
实例1
第一层爬取已经获得了一个Item对象,Item对象是一个字典,因此我们将Item对象通过meta参数,传递给第二层爬虫,第二层爬虫爬取的对象也继续添加封装到Item对象中,最终返回全部爬取的Item对象。meta就起了一个传递Item对象的作用
# coding: utf-8
import scrapy
from scrapy import Selector
from cnblogSpider.items import CnblogspiderItem
class CnblogsSpider(scrapy.Spider):
# 爬虫的名称,唯一的,最好不要文件、文件夹名称重复,以免混淆
name = 'cnblogs'
# 允许的域名
allowed_domains = ['cnblogs.com']
# 入口URL列表,爬虫启动的接口
start_urls = [
'https://www.cnblogs.com/qiyeboy/default.html?page=1'
]
# 首先定义parse方法,属于第一层爬取,
# 然后定义一格parse_body方法,属于第二层爬取(需要使用第一层爬取的url)
# parse方法,有一个response参数,该参数就是请求初始URL得到的内容
# 通过该response开始爬虫后面的各个工作
def parse(self, response):
# 实现网页的解析
# 首先抽取所有的文章,response中选择所有class='day'对应的节点元素
# 分析原文可以发现,每一篇文章都是放在,<div class="day"> </div>标签里面
# 选取的结果就是一个列表,就是多篇文章
papers = response.xpath(".//*[@class='day']")
# 从每篇文章中抽取数据
for paper in papers:
# 提取出一篇文章的地址,标题,时间,和内容(就是标题)
# .从paper下面开始选,//不管在什么位置,*所有的,class='postTitle'属性下a标签下href属性的第一个值
url = paper.xpath(".//*[@class='postTitle']/a/@href").extract()[0]
# .从paper下面开始选,//不管在什么位置,*所有的,class='postTitle'属性下a标签下的第一个文字内容
title = paper.xpath(".//*[@class='postTitle']/a/text()").extract()[0]
time = paper.xpath(".//*[@class='dayTitle']/a/text()").extract()[0]
# 提取文章的摘要
content = paper.xpath(".//*[@class='c_b_p_desc']/text()").extract()[0]
# 将提取到的数据封装成一个Item对象,封装之后类似一个字典,url为键,提取到的url地址就是值
item = CnblogspiderItem(url=url, title=title, time=time, content=content)
# 上面已经提取到了具体的一篇文章的地址,然后通过改地址,创建一个新的请求
# 通过Request类请求,传入上面解析到的文章的URL,传入一个回调方法进行网页的解析
# Request中有个meta参数,用来传递信息,传递信息的格式必须是一个字典类型,
# 通过Request传进去,通过Request的请求结果response取出来,取出方法与字典一样
request = scrapy.Request(url=url, meta={'item': item}, callback=self.parse_body)
# 将parse打造成一个生成器,生成item,经过循环之后会生成很多item字典对象
yield request # 函数生成器,相当于return返回request的值,request执行了parse_body方法,得到的就是一个item
next_page = Selector(response).re(u'<a href="(\S*)">下一页</a>')
if next_page:
# url为请求的对象,callback为回调方法,指定由谁来解析请求的响应
yield scrapy.Request(url=next_page[0], callback=self.parse)
def parse_body(self, response):
# 取出前面已经封装好的Item对象,里面已经包含了URL、标题、时间和摘要
# 这里爬取图片的URL后,继续封装到Item里面去
item = response.meta['item']
# .意思选择匹配的当前节点,//选择文档中所有匹配当前节点的节点,不考虑他们的位置,
# *匹文档中所有的元素,[@class='postBody'],匹配属性为class值为postBody的元素
# 整个表达式含义,从response元素开始匹配文档中所有属性class='postBody'的元素,实际就是匹配的文章的正文内容
body = response.xpath(".//*[@class='postBody']")
# 找出了文章正文,然后匹配里面所有的图片链接
# 下面表达式含义,从body元素节点开始匹配,找出所有的img元素下所有的src图片链接属性的值
# extract()提取所有的内容,extract_first()和extract()[0]用来提取第一个内容,有时候一个标签下面有很多文字内容
item['cimage_urls'] = body.xpath(".//img//@src").extract()
yield item # 函数生成器,相当于返回item对象
实例2
#在items模块中有下面三个参数:
import scrapy
class TextItem(spider.Item):
title = scrapy.Field()
price = scrapy.Field()
image = scrapy.Field()
#在spider爬虫中:
class TaobaoSpider(scrapy.Spider):
name = ['taobao']
allowed_domains = ['www.taobao.com']
def parse1(self,response):
'''
需要知道的是item是一个字典
'''
item = TextItem()
for product in response.css('......').extract():
item['title'] = product.css('......').extract_first()
item['price'] = product.css('......').extract_first()
url = product.css('......').extract_first()
yield = scrapy.Request(url=url, meta={'item':item} callback=self.parse2)
'''
比如我们要爬取淘宝上的商品,我们在第一层爬取时候获得了标题(title)和价格(price),
但是还想获得商品的图片,就是那些点进去的大图片,假设点进去的链接是上述代码的url,
利用scrpy.Request请求url后生成一个Request对象,通过meta参数,把item这个字典赋值给meta字典的'item'键,
即meta={'item':item},这个meta参数会被放在Request对象里一起发送给parse2()函数。
'''
def parse2(self,response):
item = response.meta['item']
for product in response.css('......').extract():
item[imgae] = product.scc('......').extract_first()
return item
'''
这个response已含有上述meta字典,此句将这个字典赋值给item,完成信息传递。
这个item已经和parse中的item一样了
之后我们就可以做图片url提取的工作了,
数据提取完成后return item ,这样就完成了数据抓取的任务了。
'''
参考博文连接:
https://blog.csdn.net/wumxiaozhu/article/details/81368689
https://www.jianshu.com/p/666edd813d55