zoukankan      html  css  js  c++  java
  • Scray框架工作原理

    Date: 2019-07-07

    Author: Sun

    1 定义

    Scrapy,Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。

    Scrapy是一个为遍历爬行网站、分解获取数据而设计的应用程序框架,它可以应用在广泛领域:数据挖掘、信息处理和或者历史片(历史记录)打包等等

    官方网站:http://scrapy.org

    2 安装

    scrapy框架的安装依赖于异步网络库twisted,安装过程很简单。

    进入到python虚拟环境下:

    pip install Scrapy

    安装过程中可能存在如下问题?

    building 'twisted.test.raiser' extension
    error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools

    解决方案
    ​ 进入下载页面:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
    ​ 下载twisted对应版本的whl文件(如我的Twisted-17.5.0-cp36-cp36m-win_amd64.whl),cp后面是python版本,amd64代表64位,运行命令:
    ​ pip install C:\Users\CR\Downloads\Twisted-17.5.0-cp36-cp36m-win_amd64.whl

    在此安装scrapy

    python -m pip install --upgrade pip -i https://pypi.douban.com/simple
    pip3 install Twisted-17.5.0-cp36-cp36m-win_amd64.whl -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
    pip3 install pywin32 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
    pip3 install scrapy -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

    说明:

    ​ 如果发现哪个库安装失败,则通过wget下载https://pypi.org/simple/中相应版本的库,并安装,最后安装就可以成功

    3 Scrapy工作原理

    ​ Scrapy框架主要由六大组件组成,它们分别是调试器(Scheduler)、下载器(Downloader)、爬虫(Spider)、中间件(Middleware)、实体管道(Item Pipeline)和Scrapy引擎(Scrapy Engine)

    3.1 组件图

    下面的图表显示了Scrapy架构组件。

    scrapy基本组件图

    组件说明:

    (1)Scrapy Engine

    引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。

    (2)调度器(Scheduler)

    调度器从引擎接受request对象,并将他们入队列,以便之后引擎请求他们时提供给引擎。

    (3)下载器(Downloader)

    下载器负责获取页面数据并提供给引擎,而后提供给spiders。

    (4)Spiders

    Spider是Scrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每个spider负责处理一个特定(或一些)网站。 更多内容请看 Spiders

    (5)Item Pipeline

    Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、 验证及持久化(例如存取到数据库中)。 更多内容查看 Item Pipeline。

    (6)下载器中间件(Downloader middlewares)

    下载器中间件是在引擎及下载器之间的特定钩子(specific hook),处理Downloader传递给引擎的response(也包括引擎传递给下载器的Request)。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。更多内容请看 下载器中间件(Downloader Middleware) 。

    一句话总结就是:处理下载请求部分

    (7)Spider中间件(Spider middlewares)

    Spider中间件是在引擎及Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出(items及requests)。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。更多内容请看 Spider中间件(Middleware)

    3.2. scrapy数据流图

    数据流程图如下:

    scrapy数据流图

    Scrapy数据流图是由执行的核心引擎(engine)控制,流程是这样的:

    1、爬虫引擎获得初始请求开始抓取。

    2、爬虫引擎开始请求调度程序,并准备对下一次的请求进行抓取。

    3、爬虫调度器返回下一个请求给爬虫引擎。

    4、引擎请求发送到下载器,通过下载中间件下载网络数据。

    5、一旦下载器完成页面下载,将下载结果返回给爬虫引擎。

    6、引擎将下载器的响应通过中间件返回给爬虫进行处理。

    7、爬虫处理响应,并通过中间件返回处理后的items,以及新的请求给引擎。

    8、引擎发送处理后的items到项目管道,然后把处理结果返回给调度器,调度器计划处理下一个请求抓取。

    9、重复该过程(继续步骤1),直到爬取完所有的url请求。

    4. Scrapy 请求响应内部组件

    4.1. 请求和响应(Request, Response)

    Scrapy的Request和Response对象用于爬取web网站。

    一般来说,Request对象在spider中被生成并且最终传递到下载器(Downloader),下载器对其进行处理并返回一个Response对象,Response对象还会返回到生成requestspider中。

    4.2. Request对象

    一个Request对象代表一个HTTP请求,一般来讲,HTTP请求是由Spider产生并被Downloader处理进而生成一个Response。

    4.2.1 构造方法:

    class scrapy.http.Request(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback, flags])
    

    一个Request对象表示一个HTTP 请求,它通常在Spider中生成并由Downloader执行,从而生成一个。

    参数:    
    url(string):请求的url
    
    callback(callable):处理响应数据的回调方法,用来解析响应数据,如果没有指定,则spider的parse方法。如果在处理期间引发异常,则会调用errback。
    
    method(string):HTTP的请求方法。默认GET。
    
    meta(dict):Request.meta属性的初始值。一旦此参数被设置,通过参数传递的字典将会被浅拷贝。
    
    body:请求体。
    
    headers(dict):请求头。
    
    cookies(dict):cookie
    
    encoding(string):编码方式,默认utf-8。
    
    priority(int):优先级,调度程序使用优先级来定义用于处理请求的顺序。具有较高优先级值的请求将会提前执行。默认0。
    
    dont_filter(boolean):请求不应该被调度器过滤。False表示过滤,True表示不过滤。默认False。
    
    errback(callable):如果在处理请求时引发异常,将会调用该函数。 这包括404 HTTP错误等失败的页面。
    
    

    4.2.2. Request.meta

    Request.meta在不同的请求之间传递数据使用的
    
    Request.meta属性可以包含任意的数据,但是Scrapy和它的内置扩展可以识别一些特殊的键。
    
    dont_redirect:不重定向
    dont_retry:不重试
    handle_httpstatus_list
    dont_merge_cookies:不合并cookie
    cookiejar:使用cookiejar
    redirect_urls:重定向连接
    bindaddress:绑定ip地址
    dont_obey_robotstxt:不遵循反爬虫协议
    download_timeout:下载超时
    

    4.2.3. Request的子类FormRequest

    FormRequest是Request的子类,一般用作表单数据提交。

    FormRequest的构造:
    class scrapy.http.FormRequest(url[,formdata,...])
    
    FormRequest类除了有Request的功能
    
    还提供一个form_response()方法:
    
    form_response(response[,formname=None,formnumber=0,formdata=None,formxpath=None,clickdata=None,dont_click=False,...])
    
    
    response:是指包含HTML表单的Response对象,该表单将用于预填充表单字段。
    
    formname:如果给定,将使用设置为该值的name属性的表单。
    
    formnumber:当响应包含多个表单时,要使用的表单的数量。 formnumber默认是0,表示使用第一个。
    
    formdata:字段来覆盖表单数据。如果一个字段已经存在于响应<form>元素中,那么它的值被在这个参数中传递的值覆盖。
    
    formxpath:如果给定,将使用与XPath匹配的第一个表单。
    
    clickdata:查找单击控件的属性。如果没有给出,表单数据将被提交模拟点击第一个可点击的元素。
    
    dont_click:如果为True,表单数据将被提交而不需要单击任何元素。
    
    

    4.3. Response对象

    HTTP请求返回的响应对象,它通常被下载(由Downloader)下载并被传送给Spider进行处理。

    4.3.1. 构造函数

    class scrapy.http.Response(url[,status=200,headers,body,flags])
    
    url:响应对象response的url
    
    headers:响应对象的响应报头
    
    status:响应的状态码,默认200。
    
    body:响应体
    
    meta:为response.meta属性的初始值。如果给定的,字典将浅复制。
    
    flags:是一个列表包含的response.flags初始值的属性。如果给定,列表将被浅拷贝。
    

    TextResponse

    class scrapy.http.TextResponse(url[,encoding[,...]])

    TextResponse对象增加了编码能力的基础响应类,是指将只用于二进制数据,如图像、声音或任何媒体文件。

    4.3.2 发送FormRequest表单请求

    ​ FormRequest新增加了一个参数formdata,接受包含表单数据的字典或者可迭代的元组,并将其转化为请求的body。并且FormRequest是继承Request的

    # 发送FormRequest表单请求
            return FormRequest.from_response(response=response,
                                             meta={'cookiejar': response.meta['cookiejar']},
                                             headers=self.post_headers,
                                             formdata={
                                                 "utf8": utf8,
                                                 "authenticity_token": authenticity_token,
                                                 "login": login,
                                                 "password": password,
                                                 "commit": commit
                                             },
                                             callback=self.after_login)
    

    案例

    有时候需要解析页面嵌套,可以采用callback, 解析页面page1,通过解析页面page2解析另一个url

    parse_page1 由url1产生response

    def parse_page1(self, response):
        item = MyItem()
        item['main_url'] = response.url
        request = scrapy.Request("http://www.example.com/some_page.html",
                                 callback=self.parse_page2)
        request.meta['item'] = item
        yield request   #将request对象发送到scheduler里面   中间要经过(request --> scheduler --> engine --> downloader --> engine --> spiders(response))
    
    
    def parse_page2(self, response):
        item = response.meta['item']
        item['other_url'] = response.url
        return item    #将item结果数据发送到pipeline里面去  结果数据 item --> pipeline
    
  • 相关阅读:
    摄影/中秋美食
    摄影/不是花中偏爱菊
    基础知识(3)- Java的基本程序设计结构
    8、分页
    洛谷——P2440 木材加工
    洛谷——P1258 小车问题
    洛谷——P1832 A+B Problem(再升级)
    洛谷——P1802 5倍经验日
    洛谷—— P1803 凌乱的yyy
    网络基础之网络协议
  • 原文地址:https://www.cnblogs.com/sunBinary/p/11147265.html
Copyright © 2011-2022 走看看