Scrapy(五):Response与Request、数据提取、Selector、Pipeline
学习自Requests and Responses — Scrapy 2.5.0 documentation
Request在Spider中生成,被Downloader执行,之后会得到网页的Response
1、Request
1)构造
scrapy.http.Request(*args,**kw)
2)构造时传入参数
参数 | 说明 | 补充 |
url | ||
callback | 对该URL的返回页面进行处理的回调函数;当该项未指定时,则默认用parse()方法 | |
method | HTTP请求方法,默认'GET' | GET、POST、PUT |
meta | 一些元数据 | |
body | 请求体 | |
headers | 请求头 | |
cookies | ||
encoding | 请求的编码方式 | |
priority | 请求优先度 | |
dont_filter | 标识该请求不被Scheduler过滤;当我们要经常用到某个request时用到 | |
errback | 异常处理方法;包括网页404错误 | |
flags | ||
cb_kwargs |
Dict;标识传入参数 return response.follow(url,self.parse_additional_page,cb_kwargs=dict(item=item) |
补充说明:
1)Request回调函数的作用时机是该request对象对应的response被下载之后,该回调函数将用该Response作为其第一个参数。举例如下:
def parse_page1(self, response):
return scrapy.Request("http://www.example.com/some_page.html",
callback=self.parse_page2) def parse_page2(self, response):
# this would log http://www.example.com/some_page.html
self.logger.info("Visited %s", response.url)
2)一些情况下我们想向回调函数传递参数,可以通过Request.cb_kwargs属性实现。举例如下:
def parse(self,response):
request = scrapy.Request(
url,
callback=self.parse_page,
cb_kwargs=dict(main_url=response.url)
)
# 为回调函数传入额外参数
request.cb_kwars['foo']='bar'
yield request #传入参数可直接写在回调函数的参数中,
#而不用通过response.xxx访问
def parse_pages(self,response,main_url,foo):
yield dict(
main_url=main_url,
ther_url=response.url,
foo=foo
)
3)使用errback处理异常情况
errback是构造Request时定义的一个异常处理函数,当有异常发生时,会调用该方法。它接收Failure作为第一个参数,可以用于追踪超时、DNS错误等。
2、Response
1)属性、方法
属性 | 类型 | 说明 |
url | ||
status | int | 响应状态码;默认200 |
headers | Dict | 响应头部 |
body | bytes | 响应正文 |
text |
str |
文本形式的响应正文 response.text = response.body.decode(response.encoding) |
encoding | str | 响应正文的编码 |
request | Request | 产生该响应的Request对象 |
meta | 与该Response对应的Request的meta属性;在构造Request对象时,可以将传递给响应处理函函数的信息通过meta参数传入;响应处理函数处理相应时,通过response.meta将信息提取出来 | |
cb_kwargs | 传入参数;与Request中的cb_kwargs相对应,通过Response.cb_kwargs提取出来 | |
selector | Selector对象用于在Response中提取数据 |
方法 | 说明 |
xpath(query) | 根据XPath路径表达式提取要素 |
css(query) | 根据CSS语法提取要素 |
urljoin(url) | 用于构造绝对url,当传入的url是一个相对地址时,根据response.url计算出相应的绝对url |
follow | 返回一个Request实例,接收与Request.__init__方法相同的参数。 |
follow_all | 返回一个Request Iterable,接收与__init__方法相同的参数。 |
部分方法的详细说明:
follow:
follow(
url, callback, mehod='GET', headers, body,
cookies, meta, encoding='utf-8', priority=0,
dont_filter=False, errback, cb_kwargs, flags
)
返回url对应的Request实例。参数写法与Request对象构建时相同,只是url可以是相对URL,而非绝对URL。
follow_all:
follow_all(
urls, callback, method='GET', headers, body,
cookies, meta, encoding='utf-8', priority=0,
dont_filter=False, errback, cb_kwargs, flags
)
返回Iterable Request,这些Requests与urls相关联。其他方面与follow方法相同。
3、用一个Spider程序来说明Request与Response
import scrapy class QuotesSpider(scrapy.Spider):
name = "quotes"
def start_requests(self):
urls = [
'http://quotes.toscrape.com/page/1/',
'http://quotes.toscrape.com/page/2/',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self,response)
page=response.url.split("/")[-2]
filename=f'quotes-{page}.html'
with open(filename,'wb') as f:
f.write(response.body)
self.log(f'Saved file {filename}')
①属性与方法
name:Spider的名字,每个Spider的名字不能相同;
start_requests:必须返回Request()的迭代器(可以是一个Requests List或yield Request())。这些Requests是针对爬虫起始URL进行的;后续的Requests将从这些初始URL中生成。
parse:对之前所有的Requests的Response进行处理,参数中的response保存了页内容并且有一系列方法来处理它。parse方法中一般将爬取到的数据保存为Dict并会自行寻找下一个新的URL(当然这也需要用yield Request(url)进行说明)。
上文的Parse中提取到的网页内容,保存在response.body中,如果要保存为二进制文件,直接保存该项就行了,如果要保存为文本文件,用response.text。
②补充
如果不想写start_requests方法,只需要设置start_urls属性,就可以不用写之前的方法,而对start_urls中的初始URL调用默认的start_requests来对这些URL进行处理。
2、数据提取
最好的提取数据方法是在scrapy shell中进行。
①以http://quotes.toscrape.com/page/1/为例,运行以下指令打开Shell
scrapy shell https://scrapy.org
②之后就可以用response的各项属性和方法进行数据提取了
response.xpath('//title/text()')
提取结果形式为:[ <Selector xpath='xpath表达式' data='提取到的信息' ]
[<Selector xpath='//title/text()' data='Scrapy | A Fast and Powerful Scraping...'>]
如果要提取其中的数据部分,可以用方法extract或getall(提取全部)、get或extract_first(提取首项),当有多个提取项时,extract、getall方法的提取结果是结果List,需要用切片[]的方式提取;也可以用join方法把所有数据连接成为一个str。
③使用正则表达式进行数据提取:re方法
用法:response.xpath('xpath表达式').re(r'正则表达式')
说明:用正则表达式对提取到的要素进行数据再提取,规则与之前正则表达式那一节所说相同,不过re方法,应该是相当于re模块下的search方法,区别在于不需要用group方法,这里re直接返回的结果就是匹配结果,如果正则表达式中有括号,则匹配结果List中保存有原文中符合匹配规则的项
In [8]: response.xpath('//title/text()').re(r'(S\w+)')
Out[8]: ['Scrapy', 'Scraping']
④用yield关键字实现自动爬取
将需要保存的内容,写为Dict形式,用yield标记,即可不停地提取并保存数据:
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').get(),
'author': quote.css('small.author::text').get(),
'tags': quote.css('div.tags a.tag::text').getall(),
}
⑤存储爬取数据
scrapy crawl 爬虫名 -o 文件 #追加写
scrapy crawl 爬虫名 -0 文件 #覆盖写 大写字母而非数字
如果要爬取的内容较多,或者更为复杂的存储类型,可以通过在pipelines.py写相应的数据存储语句。
⑥自动翻页功能:response.urlopen(next_page)
该方法只用于静态有规律的URL翻页功能。
next_page = response.urljoin(next_page)
这句话的作用是,将next_page连接到原URL上,构成新的URLnext_page;这样,利用for循环、if语句、yield语句的综合,可以实现不断爬取下一页内容的功能:
#以下代码均写在parse方法中的数据提取语句之后 for i in range(4): #假设提取前3页
next_page=response.urljoin('pw='+str(i))#得到next_page的URL
yield scrapy.Request(next_page,callback=self.parse)
⑦使用参数
方法:在运行爬虫的指定中加入-a后缀
scrapy crawl quotes -0 quotes-humor.json -a tag=humor
这些参数将传入爬虫的__init__方法中,并成为爬虫的默认参数,访问时通过self.tag在__init__中使用。
4、Selector
Selector通过XPath和CSS表达式筛选网页要素
Selector对象是response对象调用XPath与CSS方法后得到的,比如:
scrapy shell https://docs.scrapy.org/en/latest/_static/selectors-sample1.html
In [1]: response.xpath('//title/text()')
Out[1]: [<Selector xpath='//title/text()' data='Example website'>]
如果从Selector中将data提取出来,方法有很多,这里不再多说,见本文第二部分
5、Pipeline
①简介
Item被爬取之后,将被送入Pipeline进行进一步的处理。
每一个Pipeline都是一个class,这个class继承了方法process_item,该方法接收item作为参数,在该方法中对该Item进行一系列处理。
典型的处理方法有:对HTML数据的清洗、检查爬取数据的正确性、检查重复项、存储数据到数据库中。
②类方法
process_item:每个pipeline都必须实现的方法,在其中完成对item的处理
该方法必须返回1)一个Item对象;2)抛出一个DropItem异常;当抛出该异常后,对应的Item将不再会被处理。
open_spider:当Spider开始运行时调用该方法
close_spider:当Spider结束运行时调用该方法
③例子
1)保存提取到了Price的Item,修改其Price,放弃那些不含Price的Item:
from itemadapter import ItemAdapter
from scrapy.exceptions import DropItem
class PricePipeline:
def process_item(self,item,spider):
adapter = ItemAdapter(item)
if adapter.get('price'):
adapter['price'] = adapter['price'] *2
return item
else:
raise DropItem(f'Miss price in {item}')
2)把数据保存到JSON文件中
import json
from itemadapter import ItemAdapter
class JsonWriterPipeline:
def open_spider(self,spider):
self.file=open('items.jl','w')
def close_spider(self,spider):
self.file.close()
def process_item(self,item,spider):
line=json.dumps(dict(item),ensure_ascii=Flase)+'\n'
self.file.write(line)
return item
④激活Pipeline
需要在Setting中设置ITEM_PIPELINES项,才能正确激活Pipeline
ITEM_PIPELINES = {
'myproject.pipelines.PricePipeline': 300,
'myproject.pipelines.JsonWriterPipeline': 800,
}
⑤补充
在没有较多规则限制的情况下,可以在输出时直接输出为json文件,通过-o或-O实现;
Scrapy(五):Response与Request、数据提取、Selector、Pipeline的更多相关文章
- Scrapy中response属性以及内容提取
一.属性 url :HTTP响应的url地址,str类型 status:HTTP响应的状态码, int类型 headers :HTTP响应的头部, 类字典类型, 可以调用get或者getlist方法对 ...
- Scrapy 学习笔记(一)数据提取
Scrapy 中常用的数据提取方式有三种:Css 选择器.XPath.正则表达式. Css 选择器 Web 中的 Css 选择器,本来是用于实现在特定 DOM 元素上应用花括号内的样式这样一个功能的. ...
- scrapy 的response 的相关属性
Scrapy中response介绍.属性以及内容提取 解析response parse()方法的参数 response 是start_urls里面的链接爬取后的结果.所以在parse()方法中,我 ...
- Scrapy学习篇(六)之Selector选择器
当我们取得了网页的response之后,最关键的就是如何从繁杂的网页中把我们需要的数据提取出来,python从网页中提取数据的包很多,常用的有下面的几个: BeautifulSoup它基于HTML代码 ...
- scrapy获取当当网中数据
yield 1. 带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代 2. yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yiel ...
- iOS五种本地缓存数据方式
iOS五种本地缓存数据方式 iOS本地缓存数据方式有五种:前言 1.直接写文件方式:可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...
- java web 中有效解决中文乱码问题-pageEncoding与charset区别, response和request的setCharacterEncoding 区别
这里先写几个大家容易搞混的编码设置代码: 在jsp代码中的头部往往有这两行代码 pageEncoding是jsp文件本身的编码contentType的charset是指服务器发送给客户端时的内容编码J ...
- python 爬虫与数据可视化--数据提取与存储
一.爬虫的定义.爬虫的分类(通用爬虫.聚焦爬虫).爬虫应用场景.爬虫工作原理(最后会发一个完整爬虫代码) 二.http.https的介绍.url的形式.请求方法.响应状态码 url的形式: 请求头: ...
- Python爬虫框架Scrapy实例(三)数据存储到MongoDB
Python爬虫框架Scrapy实例(三)数据存储到MongoDB任务目标:爬取豆瓣电影top250,将数据存储到MongoDB中. items.py文件复制代码# -*- coding: utf-8 ...
随机推荐
- 字的研究(2)Fonttools-字体文件的解析
前言 本文主要介绍如果使用Python第三方库fontTools对TrueType字体文件(指使用TrueType描述轮廓的OpenType字体文件)的解析.修改和创建等操作. fontTools简介 ...
- salesforce零基础学习(一百一十一)custom metadata type数据获取方式更新
本篇参考: https://developer.salesforce.com/docs/atlas.en-us.234.0.apexref.meta/apexref/apex_methods_syst ...
- Java中Type接口及其子类
简介 Type是Java 编程语言中所有类型的公共高级接口,和Object不同,Object是所有类的父类,即Object是Type的父类. 分类 原始类型(Class):不仅仅包含我们平常所指的类, ...
- ARP欺骗的原理
转载请注明来源:https://www.cnblogs.com/hookjc/ 从<ARP协议工作原理>一文我们已经了解到,主机在两种情况下会保存.更新本机的ARP缓存表, 1. 接 ...
- 有关OPenCV的几个库函数的使用
转载请注明来源:https://www.cnblogs.com/hookjc/ 1) IplImage* cvCreateImage( CvSize size, int depth, int chan ...
- 文件I/O流、文件、FileInputStreaam、FileOutputStream、FileReader、FileWriter的介绍和使用
一.文件:保存数据的地方 1.文件流:文件在程序中是以流的形式类操作的 类比: 流:数据在数据源(文件)和程序(内存)之间经历的路径 输入流:数据从数据源(文件)到程序(内存)的路径 输出流:数据从程 ...
- 《手把手教你》系列技巧篇(六十五)-java+ selenium自动化测试 - cookie -下篇(详细教程)
1.简介 今天这一篇,宏哥主要讲解:利用WebDriver 提供可以读取.添加和删除cookie 信息的相关操作方法.验证浏览器中是否存在某个cookie.原因是:因为基于真实的cookie 的测试是 ...
- Python内置模块(re+collections+time等模块)
Python内置模块(re+collections+time等模块) 1. re模块 import re 在python要想使用正则必须借助于模块 re就是其中之一 1.1 findall功能( re ...
- CentOS7搭建yum源仓库(阿里源)
文章目录 注意:环境要求 1.配置服务器端yum 1.1.安装yum源工具 1.2.配置nginx 1.2.1.配置nginx页面目录 1.3.替换yum源文件 1.4.建立yum源仓库 2.配置客户 ...
- 面向对象—多态、鸭子类型(Day21)
编程原则java具有自己的编程原则和设计模式,不能多继承.python的编程原则:1.开放封闭原则:开放是对扩展是开放的,封闭是对修改是封闭的(已经写完的代码程序是不能修改的).2.依赖倒置原则:高层 ...