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. Qt获取一张图片的平均色(主色调)

    这两天在一个小工具中想做一个图标的发光效果,用固定颜色做出来效果很丑,于是想到此方法,得到图标的主色调后,将颜色调亮,并设置为阴影颜色,从而达到类似发光的效果. 本文章主要在于得到一张图片的平均色,并 ...

  2. 7.bug生命周期

    new:测试发现并提交bug,状态为new/active; open: 分配bug到开发人员,状态为open: fixed:开发人员处理完bug,将状态改为fixed: closed/reopen:测 ...

  3. 安全高效跨平台的. NET 模板引擎 Fluid 使用文档

    Liquid 是一门开源的模板语言,由 Shopify 创造并用 Ruby 实现.它是 Shopify 主题的主要构成部分,并且被用于加载店铺系统的动态内容.它是一种安全的模板语言,对于非程序员的受众 ...

  4. Windows域的管理

    目录 域的管理 默认容器 组织单位的管理 添加额外域控制器 卸载域控服务器 组策略应用 域的管理 域用户账户的管理 创建域用户账户 配置域用户账户属性 验证用户的身份 授权或拒绝对域资源的访问 组的管 ...

  5. Linux-鸟菜-5-目录配置-FHS

    Linux-鸟菜-5-目录配置-FHS 这节内容比较休闲,主要就是介绍Linux的目录配置,也就是那些目录通常是干啥的,这个比较重要,需要我们去了解.但是我觉得通常看一遍记不住啥,也就记个大概,主要还 ...

  6. [CTF]unicode编码

    [CTF]unicode编码 ---------------------  作者:adversity`  来源:CSDN  原文:https://blog.csdn.net/qq_40836553/a ...

  7. OGG-Oracle同步Sequence

    一.需求,使用OGG同步软件,将Oracle 11g Sequence实时同步到19c新库中 参考文档 Implementing replication of cyclic sequences in ...

  8. 码农飞升记-03-OpenJDK是什么?

    目录 1.OpenJDK 概述 2.OpenJDK 的发展史 3.OpenJDK Community 1.角色定义 Participant(参与者) Contributor(贡献者) OpenJDK ...

  9. layui中时间插件laydate的使用

    1.加载layui.js 2.html部分 <div class="layui-inline"> <label class="layui-form-la ...

  10. 公网IP和私有IP的区别和用途

    在Internet网络上有上千百万台主机,为了能够将这些主机区分开来,于是就给每台主机都分别配了一个专门的地址,称为IP地址. 通过IP地址就可以访问到每一台主机.IP地址由4部分数字组成,ghost ...