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 code
  • handle_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地址的IP
  • dont_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_policy
  • max_retry_times:用于每个请求的重试次数。初始化时,max_retry_times元键比RETRY_TIMES设置更高优先级

Response对象

基础参数

url——请求的url 
body——请求回来的html 
meta——用来在“页面”之间传递数据 
headers——页面的headers数据 
cookies——设置页面的cookies 
Request——发出这个response的request对象

Response对象方法

copy():同request 
replace():同request 
urljoin():由于将页面相对路径改为绝对路径 
follow():对相对路径进行自动补全

urljoin()实例:

  1. import scrapy
  2. class QuotesSpider(scrapy.Spider):
  3. name = "quotes"
  4. start_urls = [
  5. 'http://quotes.toscrape.com/page/1/',
  6. ]
  7. def parse(self, response):
  8. #使用css选择器,提取出三个元素的目录的SelectorList
  9. for quote in response.css('div.quote'):
  10. yield {
  11. #使用css选择器,提取出text元素,并把它转换成字符串
  12. 'text': quote.css('span.text::text').extract_first(),
  13. #使用css选择器,提取出author元素,并把它转换成字符串
  14. 'author': quote.css('small.author::text').extract_first(),
  15. #使用css选择器,提取出tags元素,并把它转换成List
  16. 'tags': quote.css('div.tags a.tag::text').extract(),
  17. }
  18. #使用css选择器,提取出href元素,并把它转换成字符串
  19. next_page = response.css('li.next a::attr(href)').extract_first()#取出相对路径
  20. if next_page is not None:
  21. next_page = response.urljoin(next_page) #页面相对路径改为绝对路径
  22. yield scrapy.Request(next_page, callback=self.parse)

follow()实例:

  1. import scrapy
  2. class QuotesSpider(scrapy.Spider):
  3. name = "quotes"
  4. start_urls = [
  5. 'http://quotes.toscrape.com/page/1/',
  6. ]
  7. def parse(self, response):
  8. for quote in response.css('div.quote'):
  9. yield {
  10. 'text': quote.css('span.text::text').extract_first(),
  11. 'author': quote.css('span small::text').extract_first(),
  12. 'tags': quote.css('div.tags a.tag::text').extract(),
  13. }
  14. next_page = response.css('li.next a::attr(href)').extract_first()
  15. if next_page is not None:
  16. yield response.follow(next_page, callback=self.parse) #返回一个请求实例来跟踪一个链接url

Request、Response实例演示

本节课演示使用的依旧是上节课的58同城(city58)的例子 : 
city58_test.py:本例中演示了response的follow函数中相对路径转化为绝对路径,并且比较了request中各个参数的异同

  1.  
    # -*- coding: utf-8 -*-
  2.  
    import scrapy
  3.  
    from pyquery import PyQuery
  4.  
    from ..items import City58Item
  5.  
     
  6.  
    from scrapy.http import Request
  7.  
     
  8.  
     
  9.  
    class City58TestSpider(scrapy.Spider):
  10.  
    name = 'city58_test'
  11.  
    allowed_domains = ['58.com']
  12.  
    start_urls = ['http://bj.58.com/chuzu/',
  13.  
    # 'http://bj.58.com/chuzu/pn2/'
  14.  
    ]
  15.  
     
  16.  
    def parse(self, response):
  17.  
    jpy = PyQuery(response.text)
  18.  
    li_list = jpy('body > div.mainbox > div.main > div.content > div.listBox > ul > li').items()
  19.  
    for it in li_list:
  20.  
    a_tag = it('div.des > h2 > a')
  21.  
    item = City58Item()
  22.  
    item['name'] = a_tag.text()
  23.  
    item['url'] = a_tag.attr('href')
  24.  
    item['price'] = it('div.listliright > div.money > b').text()
  25.  
     
  26.  
    test_request = response.follow('/chuzu/pn2/', callback=self.parse) #使用response.follow方法把“/chuzu/pn2/”这个相对路径转换为绝对路径,并回调parse()函数
  27.  
    test_request2 = Request('http://bj.58.com/chuzu/pn3/',
  28.  
    callback=self.parse,
  29.  
    errback=self.error_back, #调用异常函数
  30.  
    cookies={}, #cookie设为空
  31.  
    headers={}, #headers设为空
  32.  
    priority=10
  33.  
    )
  34.  
    test_request3 = Request('http://58.com',
  35.  
    callback=self.parse,
  36.  
    errback=self.error_back, #调用异常函数
  37.  
    priority=10, #优先级设为10
  38.  
    meta={'dont_redirect': True} #不用重定向
  39.  
    )
  40.  
    test_request4 = Request('http://58.com',
  41.  
    callback=self.parse,
  42.  
    errback=self.error_back,
  43.  
    priority=10,
  44.  
    # meta={'dont_redirect': True}
  45.  
    dont_filter=True #对url不过滤
  46.  
    )
  47.  
    yield item
  48.  
    yield test_request
  49.  
    yield test_request2
  50.  
    yield test_request3
  51.  
    yield test_request4
  52.  
     
  53.  
    def error_back(self, e):
  54.  
    _ = self
  55.  
    print(e) #打印异常信息

实现58同城的翻页以及详情页的爬取

items.py:定义要爬取的内容

  1.  
    import scrapy
  2.  
     
  3.  
    class City58Item(scrapy.Item):
  4.  
    name = scrapy.Field()
  5.  
    price = scrapy.Field()
  6.  
    url = scrapy.Field()
  7.  
    introduce_item = scrapy.Field()
  8.  
    address = scrapy.Field()
  9.  
    phone_number = scrapy.Field()

city58_test.py:实现58同城的翻页以及详情页的爬取

  1.  
    # -*- coding: utf-8 -*-
  2.  
    import scrapy
  3.  
    from pyquery import PyQuery
  4.  
    from ..items import City58Item
  5.  
     
  6.  
    from scrapy.http import Request
  7.  
     
  8.  
     
  9.  
    class City58TestSpider(scrapy.Spider):
  10.  
    name = 'city58_test'
  11.  
    allowed_domains = ['58.com']
  12.  
    start_urls = ['http://bj.58.com/chuzu/']
  13.  
     
  14.  
    def parse(self, response):
  15.  
    jpy = PyQuery(response.text)
  16.  
    li_list = jpy('body > div.mainbox > div.main > div.content > div.listBox > ul > li').items()
  17.  
    for it in li_list:
  18.  
    a_tag = it('div.des > h2 > a')
  19.  
    item = City58Item()
  20.  
    item['name'] = a_tag.text()
  21.  
    item['url'] = a_tag.attr('href')
  22.  
    item['price'] = it('div.listliright > div.money > b').text()
  23.  
     
  24.  
    if item['url']: #判断url是否为空
  25.  
    yield Request(item['url'],
  26.  
    callback = self.detail_parse,
  27.  
    meta = {'item':item} , #使用meta参数,把item传给detail_parse()
  28.  
    priority = 10 , #优先级设为10
  29.  
    dont_filter=True #强制不过滤)
  30.  
    )
  31.  
     
  32.  
    url = jpy('#bottom_ad_li > div.pager > a.next').attr('href') #提取翻页链接
  33.  
    test_request = Request(url,
  34.  
    callback=self.parse,
  35.  
    priority=10,
  36.  
    # meta={'dont_redirect': True}
  37.  
    dont_filter=True # 对url不过滤
  38.  
    )
  39.  
    yield test_request #实现翻页
  40.  
     
  41.  
    def detail_parse(self,response):
  42.  
    jpy = PyQuery(response.text)
  43.  
    item = response.meta['item'] #接收item
  44.  
    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() #提取房屋亮点
  45.  
    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() #房屋详情地址
  46.  
    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() #电话号码
  47.  
    return item

pipeline.py :与以前的例子相同,写入文件

  1.  
    import json
  2.  
     
  3.  
    class City58Pipeline(object):
  4.  
     
  5.  
    def open_spider(self,spider):
  6.  
    self.file = open('58_chuzu.txt', 'w' , encoding='utf8')
  7.  
    print('打开文件了')
  8.  
     
  9.  
    def process_item(self, item, spider):
  10.  
    line = '{}\n'.format(json.dumps(dict(item),ensure_ascii = False))
  11.  
    self.file.write(line)
  12.  
    return item
  13.  
     
  14.  
    def close_spider(self, spider):
  15.  
    self.file.close()
  16.  
    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参数

  1.  
    import scrapy
  2.  
     
  3.  
    class LoginSpider(scrapy.Spider):
  4.  
    name = 'example.com'
  5.  
    start_urls = ['http://www.example.com/users/login.php']
  6.  
     
  7.  
    def parse(self, response):
  8.  
    return scrapy.FormRequest.from_response(
  9.  
    response,
  10.  
    formdata={'username': 'john', 'password': 'secret'}, #预先填好的账号密码
  11.  
    callback=self.after_login
  12.  
    )
  13.  
     
  14.  
    def after_login(self, response):
  15.  
    # check login succeed before going on
  16.  
    if "authentication failed" in response.body:
  17.  
    self.logger.error("Login failed")
  18.  
    return

 

Scrapy的Request和Response的更多相关文章

  1. python的scrapy框架的使用 和xpath的使用 && scrapy中request和response的函数参数 && parse()函数运行机制

    这篇博客主要是讲一下scrapy框架的使用,对于糗事百科爬取数据并未去专门处理 最后爬取的数据保存为json格式 一.先说一下pyharm怎么去看一些函数在源码中的代码实现 按着ctrl然后点击函数就 ...

  2. Scrapy的Request和Response对象

    一.Request 发送一个请求,参数如下: url :request对象发送请求的url callback :在下载器下载完相应的数据后执行的回调函数 method :请求方法,默认为get hea ...

  3. Scrapy爬虫入门Request和Response(请求和响应)

    开发环境:Python 3.6.0 版本 (当前最新)Scrapy 1.3.2 版本 (当前最新) 请求和响应 Scrapy的Request和Response对象用于爬网网站. 通常,Request对 ...

  4. Scrapy中的Request和Response

    Request Request 部分源码: # 部分代码 class Request(object_ref): def __init__(self, url, callback=None, metho ...

  5. scrapy中的Request和Response对象

    前言: 如果框架中的组件比做成是人的各个器官的话,那个Request和Response就是血液,Item就是代谢产物 Request对象: 是用来描述一个HTTP请求,其构造参数有 url 请求的UR ...

  6. scrapy之Request对象

    我们在使用scrapy框架的时候,会经常疑惑,数据流是怎么样在各个组件中间传递的.最近经常用scrapy+selenium爬取淘宝,又因为今天周五心情好,本宝宝决定梳理一下这方面知识. scrapy中 ...

  7. Request 和 Response 原理

    * Request 和 Response 原理:     * request对象和response对象由服务器创建,我们只需要在service方法中使用这两个对象即可        * 继承体系结构: ...

  8. Request 、Response 与Server的使用

    纯属记录总结,以下图片都是来自 ASP.NET笔记之 Request .Response 与Server的使用 Request Response Server 关于Server.MapPath 方法看 ...

  9. request 和response

    当今web程序的开发技术真是百家争鸣,ASP.NET, PHP, JSP,Perl, AJAX 等等. 无论Web技术在未来如何发展,理解Web程序之间通信的基本协议相当重要, 因为它让我们理解了We ...

随机推荐

  1. poj_1700 题解

    题目描述:在漆黑的夜里,四位旅行者来到了一座狭窄而且没有护栏的桥边. 如果不借助手电筒的话,大家是无论如何也不敢过桥去的. 不幸的是,四个人一共只带了一只手电筒,而桥窄得只够让两个人同时过. 如果各自 ...

  2. K8S(18)容器环境下资源限制与jvm内存回收

    K8S(18)容器环境下资源限制与jvm内存回收 目录 K8S(18)容器环境下资源限制与jvm内存回收 一.k8s中的java资源限制与可能的问题 方案1:通过JVM的Xms和Xmx参数限制 方案2 ...

  3. 在nginx配置将请求转发到某个真实后端服务ip

    一.打开nginx机器的nginx配置文件 命令: locate nginx.conf 会列出所有nginx.conf文件的地址, 一般咱们要用的nginx配置文件是/usr/local/nginx/ ...

  4. 1045 Favorite Color Stripe

    Eva is trying to make her own color stripe out of a given one. She would like to keep only her favor ...

  5. 【ElasticSearch】ES 读数据,写数据与搜索数据的过程

    ES读数据的过程: 1.ES客户端选择一个node发送请求,该请求作为协调节点(coordinating node): 2.corrdinating node 对 doc id 对哈希,找出该文档对应 ...

  6. POJ2226 不错的最小顶点覆盖

    题意:        给你一个n * m 的矩阵,上面有" * " 和 " . " ,让你用少的木板吧所有" * "覆盖,木板宽度是1,长度 ...

  7. hdu3182 状态压缩dp

    题意:       一个人做汉堡包,每个汉堡包有自己的花费和价值,某些汉堡包必须是在其他的某些汉堡包已经做好了的前提下才能制作,给你这个人的初始钱数,问最大的价值是多少. 思路:       比较简单 ...

  8. NSIS制作安装包笔记(一):NSIS介绍、使用NSIS默认向导脚本制作Windows安装包

    前言   做产品时,定制的自定义安装界面常有的,使用NSIS + Qt可以完美的定制基于QT的安装界面,先从纯NSIS开始,制作常规的安装包.   应用程序的发布方式   应用程序发布的时候,具备以下 ...

  9. angr脚本——以angrctf解题记录为参考

    angr脚本--以angrctf解题记录为参考 ​ angr是用于逆向工程中进行二进制分析的一个python框架 ​ 符号执行 (Symbolic Execution)是一种程序分析技术.其可以通过分 ...

  10. JVM默认内存大小

    堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在Java虚拟机启动时创建的." ...