zoukankan      html  css  js  c++  java
  • Scrapy框架

    一 、介绍

        Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速、简单、可扩展的方式从网站中提取所需的数据。但目前Scrapy的用途十分广泛,可用于如数据挖掘、监测和自动化测试等领域,也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

        Scrapy 是基于twisted框架开发而来,twisted是一个流行的事件驱动的python网络框架。因此Scrapy使用了一种非阻塞(又名异步)的代码来实现并发。整体架构大致如下

      1、scrapy的工作流程

        第一步:爬虫从spiders爬行器中发送request请求给engine引擎。

        第二部:引擎发送request请求给scheduler调度器,调度器从中调度请求,并要求下一个请求进来。

        第三部:调度程序将第一个请求返回给引擎。

        第四部:引擎将请求发送给下行加载程序downloader,通过下行加载中间件,并且准备下载网页。

        第五步:一旦页面完成下载后,Downloader会生成一个响应(使用该页面)并将其发送到引擎,通过Downloader中间件到达downloader下载器

        第六步:引擎接收来自Downloader的响应,并将其发送给爬行器进行处理,通过爬行器中间件,到达爬行器

        第七步:爬行器处理响应信息,并将处理后的结果通过爬行器中间件返回到引擎。

        第八步:引擎将处理过的数据发送到项目管道,然后将处理过的请求发送到调度程序,并请求可能的下一个请求进行爬行。

      总结:

        1、引擎负责控制系统所有组件之间的数据流,并在某些动作发生时触发事件

        2、调度器用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL的优先级队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址

        3、下载器用于下载网页内容, 并将网页内容返回给EGINE,下载器是建立在twisted这个高效的异步模型上的

        4、爬虫器SPIDERS是开发人员自定义的类,用来解析responses,并且提取items,或者发送新的请求

        5、项目管道在items被提取后负责处理它们,主要包括清理、验证、持久化(比如存到数据库)等操作

        6、下载器中间件位于Scrapy引擎和下载器之间,主要用来处理从EGINE传到DOWLOADER的请求request,已经从DOWNLOADER传到EGINE的响应response,你可用该中间件做以下几件事情

          1、在发送到下载程序之前处理一个请求(即在剪贴簿发送请求到网站之前);

          2、在将其传递给蜘蛛之前,更改接收到响应;

          3、发送一个新的请求,而不是传递接收到的响应;

          4、在不获取web页面的情况下对爬行器进行响应;

          5、悄悄地放弃一些请求。

        7、爬虫中间件

          位于EGINE和SPIDERS之间,主要工作是处理SPIDERS的输入(即responses)和输出(即requests)

    官网链接:https://docs.scrapy.org/en/latest/topics/architecture.html

    二 安装

    #Windows平台
        1、pip3 install wheel #安装后,便支持通过wheel文件安装软件,wheel文件官网:https://www.lfd.uci.edu/~gohlke/pythonlibs
        3、pip3 install lxml
        4、pip3 install pyopenssl
        5、下载并安装pywin32:https://sourceforge.net/projects/pywin32/files/pywin32/
        6、下载twisted的wheel文件:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
        7、执行pip3 install 下载目录Twisted-17.9.0-cp36-cp36m-win_amd64.whl
        8、pip3 install scrapy
      
    #Linux平台
        1、pip3 install scrapy

    三 命令行工具

    #1 查看帮助
        scrapy -h      或者是scrapy -l
        scrapy <command> -h
    
    #2 有两种命令:其中Project-only必须切到项目文件夹下才能执行这种命令是局部命令,而Global的命令则不需要,是属于全局命令
        Global commands:全局命令
           1、startproject #创建一个爬虫项目,相当于创建了个爬虫的整体框架,   
            scrapy startproject 项目名称 2、genspider #创建一个爬虫程序,可以在配置文件中将网址域名注释调,该网址域名的作用就是在网站的html中只允许爬该网址的数据
            scrapy genspider 爬虫名称 需要爬的网址域名 3、settings #如果是在项目目录下,则得到的是该项目中settings的配置,否则不是,
            scrapy settings --get=settings文件中的配置变量 4、runspider #运行一个独立的python文件,不必创建项目,这个python文件可以是一个爬虫程序
            scrapy runspider 爬虫文件的绝对路径 5、shell # 在交互式调试,如选择器规则正确与否都是在该交互式环境下测试的,相当于get下来数据后将数据封装到了个response对象内。
            scrapy shell url地址
            view(response);response.text;response.body;
    6、fetch #独立于程单纯地爬取一个页面,可以拿到请求头
            scrapy fetch url地址
            scrapy fetch --header url地址 7、 view #下载完毕后直接弹出浏览器,以此可以分辨出哪些数据是ajax请求
            scrapy view rul路径 #如果页面显示内容不全,不全的内容则是ajax请求实现的,以此快速定位问题 8、version  #
            scrapy version 查看scrapy的版本
            scrapy version -v 查看scrapy所依赖的库版本
          
    Project-only commands:局部命令,必须在项目目录下才能执行 1、crawl #运行爬虫,必须创建项目程序才行,确保配置文件settings中ROBOTSTXT_OBEY = False,机器人策略,关闭该策略后就不会受机器人策略的影响
            scrapy crawl 爬虫项目文件名 #和之前的runspider方法相比该方法必须在项目目录下运行且受机器人策略的影响
            scrapy crawl 爬虫项目文件名 --nolog #运行爬虫项目不打印日志
            scrapy crawl 爬虫项目文件名 -a 参数名=参数值 #给爬虫项目传参,但是项目内部必须重新__int__方法来接受外部参数
            scrapy crawl 爬虫项目文件名 -a 参数名=参数值 --nolog #运行爬虫项目不打印日志并且传参数给爬虫项目
    2、check #检测项目(所有的爬虫程序)中有无语法错误
            scrapy check 3、list #列出项目中所包含的爬虫名
            scrapy list 4、edit #编辑器,一般不用 5、 parse # #以此可以验证我们的回调函数是否正确,回调函数一般写在爬虫程序文件下
            scrapy parse url地址 --callback 回调函数 6、bench #压力测试
            scrapy bench #3 官网链接 https://docs.scrapy.org/en/latest/topics/commands.html
    总结:在命令行的命令或者是参数都是不用加引号的,
       爬虫项目的settings配置文件添加配置时都变量名必须要大写,否则不识别

    四 项目结构以及爬虫应用简介

    project_name/
       scrapy.cfg
       project_name/
           __init__.py
           items.py
           pipelines.py
           settings.py
           spiders/
               __init__.py
               爬虫1.py
               爬虫2.py
               爬虫3.py

    文件说明:

    • scrapy.cfg  整个项目的主配置信息,用来部署scrapy时使用,爬虫相关的配置信息在settings.py文件中。
    • items.py    设置数据存储模板,用于结构化数据,如:Django的Model
    • pipelines    数据处理行为,如:一般结构化的数据持久化
    • settings.py 配置文件,如:递归的层数、并发数,延迟下载等。强调:配置文件的选项必须大写否则视为无效,正确写法USER_AGENT='xxxx'
    • spiders      爬虫目录,如:创建文件,编写爬虫规则

    注意:一般创建爬虫文件时,以网站域名命名

    import scrapy
     
    class XiaoHuarSpider(scrapy.spiders.Spider):
        name = "xiaohuar"                            # 爬虫名称 *****
        allowed_domains = ["xiaohuar.com"]  # 允许爬取的域名
        start_urls = [
            "http://www.xiaohuar.com/hua/",   # 其实URL地址,该url地址是程序默认创建的,如果需要爬取该地址外的其他地址数据就需要自己处理请求参数,重新请求方法
        ]
        def parse(self, response):
            # 访问起始URL并获取结果后的回调函数
    import sys,os
    sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')

    五 Spiders

    #在项目目录下新建:entrypoint.py
    from scrapy.cmdline import execute
    execute(['scrapy', 'crawl', 'xiaohua'])

    强调:配置文件的选项必须是大写,如X='1'

    # -*- coding: utf-8 -*-
    import scrapy
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider, Rule
    class BaiduSpider(CrawlSpider):
        name = 'xiaohua'
        allowed_domains = ['www.xiaohuar.com']
        start_urls = ['http://www.xiaohuar.com/v/']
        # download_delay = 1
        rules = (
            Rule(LinkExtractor(allow=r'p-d-d+.html$'), callback='parse_item',follow=True,),
        )
    
        def parse_item(self, response):
            if url:
                print('======下载视频==============================', url)
                yield scrapy.Request(url,callback=self.save)
    
        def save(self,response):
            print('======保存视频==============================',response.url,len(response.body))
    
            import time
            import hashlib
            m=hashlib.md5()
            m.update(str(time.time()).encode('utf-8'))
            m.update(response.url.encode('utf-8'))
    
            filename=r'E:\mv\%s.mp4' %m.hexdigest()
            with open(filename,'wb') as f:
                f.write(response.body)

    https://docs.scrapy.org/en/latest/topics/spiders.html

    六 Selectors

    response.selector.css()
    response.selector.xpath()
    可简写为
    response.css()
    response.xpath()
    
      1、查找标签
        response.css('div a ')#通过标签名查找标签的内容
        response.xpath('//body/a') #开头的//代表从整篇文档中寻找,body之后的/代表body的儿子     response.xpath('//body//a') #开头的//代表从整篇文档中寻找,body之后的//代表body的子子孙孙
        总结://与/的区别:儿子和后代的区别,但是得到的都是一个列表
      2、查找标签下的内容(text方法)      
        response.css('div a::text')#先定位标签然后通过::的方式查找标签的内容

        response.xpath('//body//a/text()')   3、查找标签下的内容
        extract与extract_first:从selector对象中解出内容    response.xpath('//div/a/text()').extract() #得到的是个解析后的内容,是个列表形式     response.xpath('//div/a/text()').extract_first()#得到的是个解析后的内容,是个字符串形式
      4、查找标签下的属性:    response.xpath('//div/a/@href').extract_first() #得到的是标签的href属性,可以跟标签的任意属性xpath的属性加前缀@ response.css('div a::attr(href)').extract_first()   5、嵌套查找加混合查找     response.xpath('//div').css('a').xpath('@href').extract_first()   6、设置查找默认值     response.xpath('//div[@id="xxx"]').extract_first(default="not found")#为了防止查找不到匹配的标签而设置默认值   7、按照标签属性查找     response.xpath('//div[@id="images"]/a[@href="image3.html"]/text()').extract() #如果按照属性查找标签就必须加上中括号,再写匹配规则     response.css('#images a[@href="image3.html"]/text()').extract()   8、按照标签属性模糊查找     response.xpath('//a[contains(@href,"image")]/@href').extract()#如果按照标签属性模糊查找就必须加上contains()方法,然后再在里面写匹配规则,匹配规则用逗号隔开     response.css('a[href*="image"]::attr(href)').extract()     response.xpath('//a[contains(@href,"image")]/img/@src').extract()     response.css('a[href*="imag"] img::attr(src)').extract()     response.xpath('//*[@href="image1.html"]')     response.css('*[href="image1.html"]')   9、正则表达式查找     response.xpath('//a/text()').re(r'Name: (.*)')     response.xpath('//a/text()').re_first(r'Name: (.*)')   10、xpath相对路径       >>> res=response.xpath('//a[contains(@href,"3")]')[0]       >>> res.xpath('img')       [<Selector xpath='img' data='<img src="image3_thumb.jpg">'>]       >>> res.xpath('./img')       [<Selector xpath='./img' data='<img src="image3_thumb.jpg">'>]       >>> res.xpath('.//img')       [<Selector xpath='.//img' data='<img src="image3_thumb.jpg">'>]       >>> res.xpath('//img') #这就是从头开始扫描   11、、带变量的xpath     response.xpath('//div[@id=$xxx]/a/text()',xxx='images').extract_first()#带变量查找     response.xpath('//div[count(a)=$yyy]/@id',yyy=5).extract_first() #求有5个a标签的div的id
    复制代码
  • 相关阅读:
    条件
    循环
    列表
    字典
    集合
    公共操作
    函数-2
    函数-1
    函数加强
    文件操作
  • 原文地址:https://www.cnblogs.com/xuanan/p/7816069.html
Copyright © 2011-2022 走看看