Scrapy的Request和Response
Scrapy的Request和Response
上节课我们学习了中间件,知道了怎么通过中间件执行反反爬策略。本节课主要介绍Scrapy框架的request对象和response对象
通常,Request对象在爬虫程序中生成并传递到系统,直到它们到达下载程序,后者执行请求并返回一个Response对象,该对象返回到发出请求的爬虫程序
Request类和Response类都有一些子类,子类用来添加基类中不必要的功能。这些在下面的请求子类和响应子类中描述
Request对象
一个Request对象表示一个HTTP请求,它通常是在爬虫中生成,并由下载器执行,从而返回Response
基础参数 :
url
——请求的url
callback
——请求回来的reseponse处理函数,也叫回调函数
meta
——用来在“页面”之间传递数据
- meta是一个dict,主要用来在解析函数之间传递值
- 比如:在
parse()
给item某些字段提取了值,并且提取出了一个新的URL,item另外一些字段需要在这个新的URL的response里面提取,为此定义一个parse_item()
解析函数用于处理这个response。在用request发送这个新的URL请求的时候,使用parse_item()作为回调函数,并使用meta传递原来已经提取的item字段给parse_item()里的response- Request对象接受一个meta参数,一个字典对象,同时Response对象有一个meta属性可以取到相应request传过来的meta
- 一旦此参数被设置, 通过参数传递的字典将会被浅拷贝
headers
——页面的headers数据
cookies
——设置页面的cookies
基础高级参数
encoding
——请求的转换编码
priority
——链接优先级
- 优先级越高,越优先爬取,但不可以序列化
序列化 (Serialization)
:将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象
dont_filter
——强制不过滤
scrapy会对request的URL去重,加上dont_filter则告诉它这个URL不参与去重
errback
——错误回掉
errback更适合用于检查记录请求产生的错误,但是不适合请求的重试
Request对象方法
copy()
:复制一个一模一样的对象replace()
:对对象参数进行替换
Request.meta 一些特殊的keys
dont_redirect
:如果 Request.meta 包含 dont_redirect 键,则该request将会被RedirectMiddleware忽略dont_retry
:如果 Request.meta 包含 dont_retry 键, 该request将会被RetryMiddleware忽略handle_httpstatus_list
:Request.meta 中的 handle_httpstatus_list 键可以用来指定每个request所允许的response codehandle_httpstatus_all
:handle_httpstatus_all为True ,可以允许请求的任何响应代码dont_merge_cookies
:Request.meta 中的dont_merge_cookies设为TRUE,可以避免与现有cookie合并cookiejar
:Scrapy通过使用 Request.meta中的cookiejar 来支持单spider追踪多cookie session。 默认情况下其使用一个cookie jar(session),不过可以传递一个标示符来使用多个dont_cache
:可以避免使用dont_cache元键等于True缓存每个策略的响应redirect_urls
:通过该中间件的(被重定向的)request的url可以通过 Request.meta 的 redirect_urls 键找到bindaddress
:用于执行请求的传出IP地址的IPdont_obey_robotstxt
:如果Request.meta将dont_obey_robotstxt键设置为True,则即使启用ROBOTSTXT_OBEY,RobotsTxtMiddleware也会忽略该请求download_timeout
:下载器在超时之前等待的时间(以秒为单位)download_maxsize
:爬取URL的最大长度download_latency
:自请求已经开始,即通过网络发送的HTTP消息,用于获取响应的时间量
该元密钥仅在下载响应时才可用。虽然大多数其他元键用于控制Scrapy行为,但是这个应用程序应该是只读的download_fail_on_dataloss
:是否在故障响应失败proxy
:可以将代理每个请求设置为像http:// some_proxy_server:port这样的值ftp_user
:用于FTP连接的用户名ftp_password
:用于FTP连接的密码referrer_policy
:为每个请求设置referrer_policymax_retry_times
:用于每个请求的重试次数。初始化时,max_retry_times元键比RETRY_TIMES设置更高优先级
Response对象
基础参数
url
——请求的urlbody
——请求回来的htmlmeta
——用来在“页面”之间传递数据headers
——页面的headers数据cookies
——设置页面的cookiesRequest
——发出这个response的request对象
Response对象方法
copy()
:同requestreplace()
:同requesturljoin()
:由于将页面相对路径改为绝对路径follow()
:对相对路径进行自动补全
urljoin()实例:
- import scrapy
- class QuotesSpider(scrapy.Spider):
- name = "quotes"
- start_urls = [
- 'http://quotes.toscrape.com/page/1/',
- ]
- def parse(self, response):
- #使用css选择器,提取出三个元素的目录的SelectorList
- for quote in response.css('div.quote'):
- yield {
- #使用css选择器,提取出text元素,并把它转换成字符串
- 'text': quote.css('span.text::text').extract_first(),
- #使用css选择器,提取出author元素,并把它转换成字符串
- 'author': quote.css('small.author::text').extract_first(),
- #使用css选择器,提取出tags元素,并把它转换成List
- 'tags': quote.css('div.tags a.tag::text').extract(),
- }
- #使用css选择器,提取出href元素,并把它转换成字符串
- next_page = response.css('li.next a::attr(href)').extract_first()#取出相对路径
- if next_page is not None:
- next_page = response.urljoin(next_page) #页面相对路径改为绝对路径
- yield scrapy.Request(next_page, callback=self.parse)
follow()实例:
- import scrapy
- class QuotesSpider(scrapy.Spider):
- name = "quotes"
- start_urls = [
- 'http://quotes.toscrape.com/page/1/',
- ]
- def parse(self, response):
- for quote in response.css('div.quote'):
- yield {
- 'text': quote.css('span.text::text').extract_first(),
- 'author': quote.css('span small::text').extract_first(),
- 'tags': quote.css('div.tags a.tag::text').extract(),
- }
- next_page = response.css('li.next a::attr(href)').extract_first()
- if next_page is not None:
- yield response.follow(next_page, callback=self.parse) #返回一个请求实例来跟踪一个链接url
Request、Response实例演示
本节课演示使用的依旧是上节课的58同城(city58)的例子 : city58_test.py
:本例中演示了response的follow函数中相对路径转化为绝对路径,并且比较了request中各个参数的异同
- # -*- coding: utf-8 -*-
- import scrapy
- from pyquery import PyQuery
- from ..items import City58Item
- from scrapy.http import Request
- class City58TestSpider(scrapy.Spider):
- name = 'city58_test'
- allowed_domains = ['58.com']
- start_urls = ['http://bj.58.com/chuzu/',
- # 'http://bj.58.com/chuzu/pn2/'
- ]
- def parse(self, response):
- jpy = PyQuery(response.text)
- li_list = jpy('body > div.mainbox > div.main > div.content > div.listBox > ul > li').items()
- for it in li_list:
- a_tag = it('div.des > h2 > a')
- item = City58Item()
- item['name'] = a_tag.text()
- item['url'] = a_tag.attr('href')
- item['price'] = it('div.listliright > div.money > b').text()
- test_request = response.follow('/chuzu/pn2/', callback=self.parse) #使用response.follow方法把“/chuzu/pn2/”这个相对路径转换为绝对路径,并回调parse()函数
- test_request2 = Request('http://bj.58.com/chuzu/pn3/',
- callback=self.parse,
- errback=self.error_back, #调用异常函数
- cookies={}, #cookie设为空
- headers={}, #headers设为空
- priority=10
- )
- test_request3 = Request('http://58.com',
- callback=self.parse,
- errback=self.error_back, #调用异常函数
- priority=10, #优先级设为10
- meta={'dont_redirect': True} #不用重定向
- )
- test_request4 = Request('http://58.com',
- callback=self.parse,
- errback=self.error_back,
- priority=10,
- # meta={'dont_redirect': True}
- dont_filter=True #对url不过滤
- )
- yield item
- yield test_request
- yield test_request2
- yield test_request3
- yield test_request4
- def error_back(self, e):
- _ = self
- print(e) #打印异常信息
实现58同城的翻页以及详情页的爬取
items.py
:定义要爬取的内容
- import scrapy
- class City58Item(scrapy.Item):
- name = scrapy.Field()
- price = scrapy.Field()
- url = scrapy.Field()
- introduce_item = scrapy.Field()
- address = scrapy.Field()
- phone_number = scrapy.Field()
city58_test.py
:实现58同城的翻页以及详情页的爬取
- # -*- coding: utf-8 -*-
- import scrapy
- from pyquery import PyQuery
- from ..items import City58Item
- from scrapy.http import Request
- class City58TestSpider(scrapy.Spider):
- name = 'city58_test'
- allowed_domains = ['58.com']
- start_urls = ['http://bj.58.com/chuzu/']
- def parse(self, response):
- jpy = PyQuery(response.text)
- li_list = jpy('body > div.mainbox > div.main > div.content > div.listBox > ul > li').items()
- for it in li_list:
- a_tag = it('div.des > h2 > a')
- item = City58Item()
- item['name'] = a_tag.text()
- item['url'] = a_tag.attr('href')
- item['price'] = it('div.listliright > div.money > b').text()
- if item['url']: #判断url是否为空
- yield Request(item['url'],
- callback = self.detail_parse,
- meta = {'item':item} , #使用meta参数,把item传给detail_parse()
- priority = 10 , #优先级设为10
- dont_filter=True #强制不过滤)
- )
- url = jpy('#bottom_ad_li > div.pager > a.next').attr('href') #提取翻页链接
- test_request = Request(url,
- callback=self.parse,
- priority=10,
- # meta={'dont_redirect': True}
- dont_filter=True # 对url不过滤
- )
- yield test_request #实现翻页
- def detail_parse(self,response):
- jpy = PyQuery(response.text)
- item = response.meta['item'] #接收item
- item['introduce_item'] = jpy('body > div.main-wrap > div.house-detail-desc > div.main-detail-info.fl > div.house-word-introduce.f16.c_555 > ul > li:nth-child(1) > span.a2').text() #提取房屋亮点
- item['address'] = jpy('body > div.main-wrap > div.house-basic-info > div.house-basic-right.fr > div.house-basic-desc > div.house-desc-item.fl.c_333 > ul > li:nth-child(6) > span.dz').text() #房屋详情地址
- item['phone_number'] = jpy('body > div.main-wrap > div.house-basic-info > div.house-basic-right.fr > div.house-fraud-tip > div.house-chat-phone > span').text() #电话号码
- return item
pipeline.py
:与以前的例子相同,写入文件
- import json
- class City58Pipeline(object):
- def open_spider(self,spider):
- self.file = open('58_chuzu.txt', 'w' , encoding='utf8')
- print('打开文件了')
- def process_item(self, item, spider):
- line = '{}\n'.format(json.dumps(dict(item),ensure_ascii = False))
- self.file.write(line)
- return item
- def close_spider(self, spider):
- self.file.close()
- print('关闭文件了')
补充资料
使用FormRequest.from_response()方法模拟用户登录:
FormRequest类扩展了基本请求,具有处理HTML表单的功能。它使用lxml.html表单从表单数据预先填充表单域从响应对象
除了标准的Request方法之外,FormRequest对象还支持以下类方法:
classmethod from_response(response[, formname=None, formid=None, formnumber=0, formdata=None, formxpath=None, formcss=None, clickdata=None, dont_click=False, ...])
返回一个新的FormRequest对象,其表单字段值预先填充在给定响应中包含的HTML <form>
元素中
该policy是默认情况下自动模拟任何可以点击的表单控件,如 < input type =“submit” >。即使这是非常方便的,通常是期望的行为,有时它可能会导致难以调试的问题。例如,使用javascript填充和/或提交的表单时,默认的from_response()行为可能不是最合适的。要禁用此行为,您可以将dont_click参数设置为True。另外,如果要更改点击的控件(而不是禁用它),还可以使用clickdata参数
- import scrapy
- class LoginSpider(scrapy.Spider):
- name = 'example.com'
- start_urls = ['http://www.example.com/users/login.php']
- def parse(self, response):
- return scrapy.FormRequest.from_response(
- response,
- formdata={'username': 'john', 'password': 'secret'}, #预先填好的账号密码
- callback=self.after_login
- )
- def after_login(self, response):
- # check login succeed before going on
- if "authentication failed" in response.body:
- self.logger.error("Login failed")
- return
Scrapy的Request和Response的更多相关文章
- python的scrapy框架的使用 和xpath的使用 && scrapy中request和response的函数参数 && parse()函数运行机制
这篇博客主要是讲一下scrapy框架的使用,对于糗事百科爬取数据并未去专门处理 最后爬取的数据保存为json格式 一.先说一下pyharm怎么去看一些函数在源码中的代码实现 按着ctrl然后点击函数就 ...
- Scrapy的Request和Response对象
一.Request 发送一个请求,参数如下: url :request对象发送请求的url callback :在下载器下载完相应的数据后执行的回调函数 method :请求方法,默认为get hea ...
- Scrapy爬虫入门Request和Response(请求和响应)
开发环境:Python 3.6.0 版本 (当前最新)Scrapy 1.3.2 版本 (当前最新) 请求和响应 Scrapy的Request和Response对象用于爬网网站. 通常,Request对 ...
- Scrapy中的Request和Response
Request Request 部分源码: # 部分代码 class Request(object_ref): def __init__(self, url, callback=None, metho ...
- scrapy中的Request和Response对象
前言: 如果框架中的组件比做成是人的各个器官的话,那个Request和Response就是血液,Item就是代谢产物 Request对象: 是用来描述一个HTTP请求,其构造参数有 url 请求的UR ...
- scrapy之Request对象
我们在使用scrapy框架的时候,会经常疑惑,数据流是怎么样在各个组件中间传递的.最近经常用scrapy+selenium爬取淘宝,又因为今天周五心情好,本宝宝决定梳理一下这方面知识. scrapy中 ...
- Request 和 Response 原理
* Request 和 Response 原理: * request对象和response对象由服务器创建,我们只需要在service方法中使用这两个对象即可 * 继承体系结构: ...
- Request 、Response 与Server的使用
纯属记录总结,以下图片都是来自 ASP.NET笔记之 Request .Response 与Server的使用 Request Response Server 关于Server.MapPath 方法看 ...
- request 和response
当今web程序的开发技术真是百家争鸣,ASP.NET, PHP, JSP,Perl, AJAX 等等. 无论Web技术在未来如何发展,理解Web程序之间通信的基本协议相当重要, 因为它让我们理解了We ...
随机推荐
- P2P技术(一):NAT
1.NAT由来 NAT是一项神奇的技术,说它神奇在于它的出现几乎使IPv4起死回生.在IPv4已经被认为行将结束历史使命之后近20年时间里,人们几乎忘了IPv4的地址空间即将耗尽这样一个事实--在新技 ...
- 【DB宝50】Oracle异构平台迁移之完全可传输导出导入(Full Transportable Export & Import)
目录 一.简介 1.1.使用场景 1.2.限制条件 二.完全可传输操作步骤 三.案例演示 3.1.环境 3.2.源库操作 3.2.1.将需要传输的用户表空间设置为RO状态 3.2.2.使用Data P ...
- android添加账户源码浅析
上篇粗略的分析android添加账号的流程,本篇深入的解析下执行步骤.先来看图片,取自深入理解android卷2: 上图详细的分析了addAccount的流程,下面我们结合源码来理解它 1.addAc ...
- 网站指纹识别工具Whatweb的使用
目录 whatweb 一些常见的Whatweb的扫描 常规扫描 批量扫描 详细回显扫描 扫描强度等级控制 快速本地扫描(扫描内网的主机) 将扫描结果导出至文件内 whatweb whatweb 是ka ...
- windows核心编程-第一章 对程序错误的处理
第一章-对程序错误的处理 在开始介绍Microsoft Windows 的特性之前,必须首先了解 Wi n d o w s的各个函数是如何进行错误处理的. 当调用一个Wi n d o w s函数时,它 ...
- Node-RESTful
//获取用户列表------------------------------------------------- var express = require('express'); var app ...
- [CTF]URL编码
[CTF]URL编码 --------------------- 作者:adversity` 来源:CSDN 原文:https://blog.csdn.net/qq_40836553/artic ...
- git修改远端仓库地址
git remote set-url origin 远端地址
- Pytest自动化测试-简易入门教程(03)
今天分享内容的重点,和大家来讲一下我们的测试框架--Pytest 讲到这个框架的话呢,可能有伙伴就会问老师,我在学习自动化测试过程中,我们要去学一些什么东西? 第一个肯定要学会的是一门编程语言,比如说 ...
- 没有发生GC也进入了安全点?这段关于安全点的JVM源码有点意思!
文末 JVM 思维导图,有需要的可以自取 熟知并发编程的你认为下面这段代码的执行结果是怎么样的? 我如果说,执行流程是: t1 线程和 t2 线程一直执行 num 的累加操作 主线程睡眠 1 秒,1 ...