美文网首页
06 scrapy框架

06 scrapy框架

作者: yungege | 来源:发表于2019-08-05 22:41 被阅读0次

    06 scrapy框架

    Scrapy是纯Python开发的一个高效,结构化的网页抓取框架;

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。 Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试 Scrapy使用了Twisted 异步网络库来处理网络通讯。

    一、简单使用

    1、新建项目

    语法格式:scrapy startproject <project_name> [project_dir]
    该命令会在project_dir文件加下创建一个名为project_name的Scrapy新项目。如果project_dir没有指定,project_dir与project_name相同。
    进入你想要存放项目的目录下运行一下命令:
    scrapy startproject tz_spider
    该命令会在当前目录创建包含一下文件的名为tz_spider的目录。

    scrapy startproject mingyan
    

    2、编写爬虫

    创建一个TzcSpider的类,它必须继承scrapy.Spider类,需要定义一下三个属性:
    name: spider的名字,必须且唯一
    start_urls: 初始的url列表
    parse(self, response) 方法:每个初始url完成之后被调用。这个函数要完成一下两个功能:
    解析响应,封装成item对象并返回这个对象
    提取新的需要下载的url,创建新的request,并返回它
    我们也可以通过命令创建爬虫
    语法格式:scrapy genspider [-t template] <name> <domain>
    运行命令:scrapy genspider tzc www.shiguangkey.com
    会在spiders文件下生成tzc.py文件,文件内容如下:

    # -*- coding: utf-8 -*-
    import scrapy
    
    class TzcSpider(scrapy.Spider):
        name = 'tzc'
        # allowed_domains = ['www.']
        start_urls = ['http://www.shiguangkey.com/']
    
        def parse(self, response):
            pass
    

    3、文件分析

    1)scrapy.cfg: 项目的配置文件,现在可以先忽略。

    2)tanzhou_spider.py: 该项目的python模块

    3)items.py: 项目中的item文件。

    Item 是保存爬取到的数据的容器;其使用方法和python字典类似, 并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。

    4)pipelines.py: 项目中的pipelines文件。

    Scrapy提供了pipeline模块来执行保存数据的操作。在创建的 Scrapy 项目中自动创建了一个 pipeline.py 文件,同时创建了一个默认的 Pipeline 类。比如我们要把item提取的数据保存到mysql数据库 。

    5)settings.py: 项目的设置文件。

    settings.py是Scrapy中比较重要的配置文件,里面可以设置的内容非常之多。比如我们在前面提到的在pipelines.py中编写了把数据保存到mysql数据的class。

    6)middlewares.py:中间件。

    4、提取数据

    css选择器、xpath选择器、正则

    1)css选择器

    # 提取a标签
    response.css("a")
    # 提取a标签的href属性的值
    response.css("a::attr(href)")
    # 提取a标签的文档内容
    response.css("a::text")
    
    CSS 高级用法:
    CSS选择器用于选择你想要的元素的样式的模式。"CSS"列表示在CSS版本的属性定义(CSS1,CSS2,或对CSS3)。
    
    选择器 示例  示例说明    CSS
    .class  .intro  选择所有class="intro"的元素    1
    #id #firstname  选择所有id="firstname"的元素   1
    *   *   选择所有元素  2
    element p   选择所有<p>元素   1
    element,element div,p   选择所有<div>元素和<p>元素   1
    element element div p   选择<div>元素内的所有<p>元素  1
    element>element div>p   选择所有父级是 <div> 元素的 <p> 元素    2
    element+element div+p   选择所有紧接着<div>元素之后的<p>元素  2
    [attribute] [target]    选择所有带有target属性元素    2
    [attribute=value]   [target=-blank] 选择所有使用target="-blank"的元素    2
    [attribute~=value]  [title~=flower] 选择标题属性包含单词"flower"的所有元素 2
    [attribute|=language]   [lang|=en]  选择一个lang属性的起始值="EN"的所有元素    2
    :link   a:link  选择所有未访问链接   1
    :visited    a:visited   选择所有访问过的链接  1
    :active a:active    选择活动链接  1
    :hover  a:hover 选择鼠标在链接上面时  1
    :focus  input:focus 选择具有焦点的输入元素 2
    :first-letter   p:first-letter  选择每一个<P>元素的第一个字母    1
    :first-line p:first-line    选择每一个<P>元素的第一行  1
    :first-child    p:first-child   指定只有当<p>元素是其父级的第一个子级的样式。    2
    :before p:before    在每个<p>元素之前插入内容  2
    :after  p:after 在每个<p>元素之后插入内容  2
    :lang(language) p:lang(it)  选择一个lang属性的起始值="it"的所有<p>元素 2
    element1~element2   p~ul    选择p元素之后的每一个ul元素 3
    [attribute^=value]  a[src^="https"] 选择每一个src属性的值以"https"开头的元素   3
    [attribute$=value]  a[src$=".pdf"]  选择每一个src属性的值以".pdf"结尾的元素    3
    [attribute*=value]  a[src*="runoob"]    选择每一个src属性的值包含子字符串"runoob"的元素   3
    :first-of-type  p:first-of-type 选择每个p元素是其父级的第一个p元素  3
    :last-of-type   p:last-of-type  选择每个p元素是其父级的最后一个p元素 3
    :only-of-type   p:only-of-type  选择每个p元素是其父级的唯一p元素   3
    :only-child p:only-child    选择每个p元素是其父级的唯一子元素   3
    :nth-child(n)   p:nth-child(2)  选择每个p元素是其父级的第二个子元素  3
    :nth-last-child(n)  p:nth-last-child(2) 选择每个p元素的是其父级的第二个子元素,从最后一个子项计数   3
    :nth-of-type(n) p:nth-of-type(2)    选择每个p元素是其父级的第二个p元素  3
    :nth-last-of-type(n)    p:nth-last-of-type(2)   选择每个p元素的是其父级的第二个p元素,从最后一个子项计数   3
    :last-child p:last-child    选择每个p元素是其父级的最后一个子级。 3
    :root   :root   选择文档的根元素    3
    :empty  p:empty 选择每个没有任何子级的p元素(包括文本节点)  3
    :target #news:target    选择当前活动的#news元素(包含该锚名称的点击的URL)   3
    :enabled    input:enabled   选择每一个已启用的输入元素   3
    :disabled   input:disabled  选择每一个禁用的输入元素    3
    :checked    input:checked   选择每个选中的输入元素 3
    :not(selector)  :not(p) 选择每个并非p元素的元素    3
    ::selection ::selection 匹配元素中被用户选中或处于高亮状态的部分    3
    :out-of-range   :out-of-range   匹配值在指定区间之外的input元素  3
    :in-range   :in-range   匹配值在指定区间之内的input元素  3
    :read-write :read-write 用于匹配可读及可写的元素    3
    :read-only  :read-only  用于匹配设置 "readonly"(只读) 属性的元素 3
    :optional   :optional   用于匹配可选的输入元素 3
    :required   :required   用于匹配设置了 "required" 属性的元素    3
    :valid  :valid  用于匹配输入值为合法的元素   3
    :invalid    :invalid    用于匹配输入值为非法的元素   3
    

    2)xpath选择器

    提取a标签
    response.xpath('//a')

    提取class="inp"的a标签的href内容

    response.xpath('//a[@class="inp"]/@href')

    提取class="inp"的a标签的文本内容

    response.xpath('//a[@class="inp"]/text()')

    路径表达式 结果
    /bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
    /bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
    /bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
    /bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
    //title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
    //title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
    /bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
    /bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。
    路径表达式 结果
    bookstore 选取 bookstore 元素的所有子节点。
    /bookstore
    选取根元素 bookstore。

    注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!

    bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
    //book 选取所有 book 子元素,而不管它们在文档中的位置。
    bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
    //@lang 选取名为 lang 的所有属性。
    XPath 通配符可用来选取未知的 HTML元素。

    通配符 描述

    • 匹配任何元素节点。
      • 匹配任何属性节点。
        de() 匹配任何类型的节点。
        在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

        表达式 结果
        ookstore/* 选取 bookstore 元素的所有子元素。

        • 选取文档中的所有元素。
          itle[@*] 选取所有带有属性的 title 元素。

    3)正则

    response.css("a").re('href="(.*?)"')
    

    4)extract()、extract_first()

    # 将符合要求的数据提取到列表中
    response.css("a").re('href="(.*?)"').extract()
    # 将符合要求的数据的第一条提取出来
    response.css("a").re('href="(.*?)"').extract()
    

    5、运行爬虫

    首先进入项目根目录,然后运行命令:scrapy crawl tzc就可以启动爬虫了。 这个命令会启动我们刚才创建的那个名为tzc的爬虫,你会在屏幕上得到类似左图的输出。

    scrapy crawl tzc
    # 无日志运行
    scrapy crawl tzc --nolog
    # 查看本工程中有哪些spider
    scrapy list
    

    6、追踪链接

    #爬取多页数据,返回一个scrapy.Request对象
    import scrapy
    
    class TzcSpider(scrapy.Spider):
        name = 'tzc'
        # allowed_domains = ['www.']
        start_urls = ['https://ke.qq.com/course/list?mt=1001/']
    
        def parse(self, response):
            url = response.url
            next_url = response.xpath('//a[@class="page-next-btn icon-font i-v-right"]/@href').extract_first()
            # 返回一个request请求
            return scrapy.Request(next_url,callback=self.parse)
    
    # -*- coding: utf-8 -*-
    import scrapy
    
    
    class TanzhouSpiderSpider(scrapy.Spider):
        name = 'tanzhou_spider'
        # allowed_domains = ['www']
        start_urls = ['https://www.qiushibaike.com/hot']
    
        def parse(self, response):
            next_url = response.xpath('//ul[@class="pagination"]/li/a/span[text()="\n下一页\n"]').xpath('../@href').extract_first()
            detial_urls = response.xpath('//div[@id="content-left"]/div/a/@href').extract()
            if detial_urls:
                detial_urls = list(set(detial_urls))
                for detial_url in detial_urls:
                    detial_url = 'https://www.qiushibaike.com' + detial_url
                    print(detial_url)
                    yield scrapy.Request(detial_url, callback=self.detial_parse)
            if next_url:
                next_url = 'https://www.qiushibaike.com'+ next_url
                print(next_url)
                return scrapy.Request(next_url, callback=self.parse)
    
    
        def detial_parse(self,response):
            print(response.url)
    

    7、定义管道

    parse函数在解析出我们需要的信息之后,可以将这些信息打包成一个字典对象或scray.Item对象(一般都是item对象,下面我们再讲),然后返回。这个对象会被发送到item管道,该管道会通过顺序执行几个组件处理它。每个item管道组件是一个实现简单方法的Python类。他们收到一个item并对其执行操作,同时决定该item是否应该继续通过管道或者被丢弃并且不再处理。

    item管道的典型用途是:

    清理HTML数据
    验证已删除的数据(检查项目是否包含某些字段)
    检查重复项(并删除它们)
    将已爬取的item进行数据持久化

    items.py

    import scrapy
    class MyspiderItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        url = scrapy.Field()
        next_url = scrapy.Field()
        pass
    

    pipelines.py

    # 编写管道类
    import json
    
    class MyspiderPipeline(object):
        def open_spider(self,spider):
            self.f = open("course.txt","w",encoding="utf-8")
            # pass
    
        def process_item(self, item, spider):
            self.f.write(json.dumps(dict(item),ensure_ascii=False))
            self.f.write("\n")
            return item
    
        def close_spider(self,spider):
            self.f.close()
    
    # pass
    

    激活管道组件 settings.py,类后面的数字代表优先等级

    ITEM_PIPELINES = {
       'MySpider.pipelines.MyspiderPipeline': 300,
    }
    # 君子协议
    # Obey robots.txt rules
    ROBOTSTXT_OBEY = False
    

    8、数据写入文件、数据库

    class SomethingPipeline(object):
        def __init__(self):    
            # 可选实现,做参数初始化等
            # doing something
    
        def process_item(self, item, spider):
            # item (Item 对象) – 被爬取的item
            # spider (Spider 对象) – 爬取该item的spider
            # 这个方法必须实现,每个item pipeline组件都需要调用该方法,
            # 这个方法必须返回一个 Item 对象,被丢弃的item将不会被之后的pipeline组件所处理。
            return item
    
        def open_spider(self, spider):
            # spider (Spider 对象) – 被开启的spider
            # 可选实现,当spider被开启时,这个方法被调用。
    
        def close_spider(self, spider):
            # spider (Spider 对象) – 被关闭的spider
            # 可选实现,当spider被关闭时,这个方法被调用
    

    写入文件

    import json
    
    class ItcastJsonPipeline(object):
    
        def __init__(self):
            self.file = open('teacher.json', 'wb')
    
        def process_item(self, item, spider):
            content = json.dumps(dict(item), ensure_ascii=False) + "\n"
            self.file.write(content)
            return item
    
        def close_spider(self, spider):
            self.file.close()
    

    写入mysql

    # 将item写入数据库
    # 小数据可以使用同步写入
    import pymysql
    class MysqlPipeine(object):
        def __init__(self):
            self.db_config = {
                                'user': 'aliyun',
                                'password': '123456',
                                'db': 'class37',
                                'charset': 'utf8',
                            }
            # 建立连接
            self.conn = pymysql.connect(**self.db_config)
            # 创建游标
            self.cursor = self.conn.cursor()
            
        # 处理item的函数
        def process_item(self,item,spider):
            # 准备sql语句
            sql = 'insert into student value(item)'
            self.cursor.execute(sql)
            self.conn.commit()
        
        # 关闭数据库连接
        def close_spider(self,spider):
            self.cursor.close()
            self.conn.close()
    

    二、运行流程

    上图显示了Scrapy框架的体系结构及其组件,以及系统内部发生的数据流(由红色的箭头显示。)
    Scrapy中的数据流由执行引擎控制,流程如下:

    1、运行流程

    首先从爬虫获取初始的请求
    将请求放入调度模块,然后获取下一个需要爬取的请求
    调度模块返回下一个需要爬取的请求给引擎
    引擎将请求发送给下载器,依次穿过所有的下载中间件
    一旦页面下载完成,下载器会返回一个响应包含了页面数据,然后再依次穿过所有的下载中间件。
    引擎从下载器接收到响应,然后发送给爬虫进行解析,依次穿过所有的爬虫中间件
    爬虫处理接收到的响应,然后解析出item和生成新的请求,并发送给引擎
    引擎将已经处理好的item发送给管道组件,将生成好的新的请求发送给调度模块,并请求下一个请求
    该过程重复,直到调度程序不再有请求为止。

    2、组件介绍

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

    调度程序
    调度程序接收来自引擎的请求,将它们排入队列,以便稍后引擎请求它们。

    下载器
    下载程序负责获取web页面并将它们提供给引擎,引擎再将它们提供给spider。

    爬虫
    爬虫是由用户编写的自定义的类,用于解析响应,从中提取数据,或其他要抓取的请求。

    item管道

    管道负责在数据被爬虫提取后进行后续处理。典型的任务包括清理,验证和持久性(如将数据存储在数据库中)框架。它使用非阻塞(也成为异步)代码实现并发。

    下载中间件
    下载中间件是位于引擎和下载器之间的特定的钩子,它们处理从引擎传递到下载器的请求,以及下载器传递到引擎的响应。
    如果你要执行以下操作之一,请使用Downloader中间件:
    在请求发送到下载程序之前处理请求(即在scrapy将请求发送到网站之前)
    在响应发送给爬虫之前
    直接发送新的请求,而不是将收到的响应传递给蜘蛛
    将响应传递给爬行器而不获取web页面;
    默默的放弃一些请求

    爬虫中间件
    爬虫中间件是位于引擎和爬虫之间的特定的钩子,能够处理传入的响应和传递出去的item和请求。
    如果你需要以下操作请使用爬虫中间件:
    处理爬虫回调之后的 请求或item
    处理start_requests
    处理爬虫异常
    根据响应内容调用errback而不是回调请求
    事件驱动的网络

    scrapy 是用Twisted编写的,Twisted是一个流行的事件驱动的Python网络框架。它使用非阻塞(也成为异步)代码实现并发。

    3、编写流程

    scrapy爬虫编写流程

    1、创建爬虫项目

    scrapy startproject mingyan
    

    2、创建spider文件

    scrapy genspider tzc_spider www.shiguangkey.com
    

    3、编写items文件

    知道需要爬取的数据

    4、解析数据

    提取Request或者items

    5、保存数据

    pipelines.py中保存数据
    settings.py 激活管道

    三、媒体管道

    1、媒体管道特性

    媒体管道都实现了以下特性:
    避免重新下载最近下载的媒体
    指定存储位置(文件系统目录,Amazon S3 bucket,谷歌云存储bucket)
    图像管道具有一些额外的图像处理功能:
    将所有下载的图片转换为通用格式(JPG)和模式(RGB)
    生成缩略图
    检查图像的宽度/高度,进行最小尺寸过滤

    2、工作流程

    它的工作流是这样的:

    1.在爬虫中,您可以返回一个item,并将所需的url放入file_urls字段。
    2.item从爬虫返回并进入item管道。
    3.当item到达文件管道时,file_urls字段中的url将使用标准的Scrapy调度器和下载程序(这意味着将重用调度器和下载程序中间件)计划下载, 但是具有更高的优先级,在其他页面被爬取之前处理它们。在文件下载完成(或由于某种原因失败)之前,该项在特定管道阶段保持“锁定”状态。
    4.下载文件后,将使用另一个字段(files)填充results。这个字段将包含一个包含有关下载文件信息的dicts列表,例如下载的路径、原始的剪贴url(从file_urls字段中获得)和文件校验和。文件字段列表中的文件将保持原来file_urls字段的顺序。如果某些文件下载失败,将记录一个错误,文件将不会出现在files字段中。

    3、API

    # 在媒体管道中,我们可以重写的方法:
    # get_media_requests(item, info) 根据item中的file_urls/image_urls生成请求
    
    def get_media_requests(self, item, info):
        for file_url in item['file_urls']:
            yield scrapy.Request(file_url)
    
    # item_completed(requests, item, info)  当item里的 所有媒体文件请求完成调用
    
    from scrapy.exceptions import DropItem
    def item_completed(self, results, item, info):
        file_paths = [x['path'] for ok, x in results if ok]
        if not file_paths:
              raise DropItem("Item contains no files")
        item['file_paths'] = file_paths
        return item
    
    # file_path 可以变保存文件的路径
    def file_path(self, request, response=None, info=None):
        # 提取url前面名称作为图片名。
        image_guid = request.url.split('/')[-1]
        # 接收上面meta传递过来的图片名称
        name = request.meta['name']
        # 分文件夹存储的关键:{0}对应着name;{1}对应着image_guid
        filename = u'{0}/{1}'.format(name, image_guid)
        return filename
    

    4、媒体管道的设置

    ITEM_PIPELINES = {'scrapy.pipelines.images.ImagesPipeline': 1}  启用
    FILES_STORE = '/path/to/valid/dir'      文件管道存放位置
    IMAGES_STORE = '/path/to/valid/dir'     图片管道存放位置
    FILES_URLS_FIELD = 'field_name_for_your_files_urls'    自定义文件url字段
    FILES_RESULT_FIELD = 'field_name_for_your_processed_files'   自定义结果字段
    IMAGES_URLS_FIELD = 'field_name_for_your_images_urls'  自定义图片url字段
    IMAGES_RESULT_FIELD = 'field_name_for_your_processed_images'  结果字段
    FILES_EXPIRES = 90    文件过期时间   默认90天
    IMAGES_EXPIRES = 90    图片过期时间   默认90天
    IMAGES_THUMBS = {'small': (50, 50), 'big':(270, 270)}  缩略图尺寸
    IMAGES_MIN_HEIGHT = 110   过滤最小高度
    IMAGES_MIN_WIDTH = 110   过滤最小宽度
    MEDIA_ALLOW_REDIRECTS = True    是否重定向
    

    5、自定义图片管道

    pipelines.py

    from scrapy.pipelines.images import ImagesPipeline
    from scrapy import Request
    
    # 继承 ImagesPipeline
    class DownloadimagePipeline(ImagesPipeline):
        
        # 需要注释掉process_item,否则不能执行get_media_requests()
        # def process_item(self, item, spider):
        #     print(item,'=================')
        #     return item
    
        def get_media_requests(self, item, info):
            # 循环每一张图片地址下载,若传过来的不是集合则无需循环直接yield
            for image_url in item['img_urls']:
                # 将 img_names值通过meta传到后面
                yield Request(image_url, meta={'name': item['img_names']})
    
        def file_path(self, request, response=None, info=None):
            # 提取url前面名称作为图片名。
            image_guid = request.url.split('/')[-1]
            # 接收上面meta传递过来的图片名称
            name = request.meta['name']
            # 分文件夹存储的关键:{0}对应着name;{1}对应着image_guid
            filename = u'{0}/{1}'.format(name, image_guid)
            return filename
    

    settings.py

    # Configure item pipelines
    # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    ITEM_PIPELINES = {
       'DownloadImage.pipelines.DownloadimagePipeline': 300,
    }
    
    import os
    #配置保存本地的地址
    project_dir=os.path.abspath(os.path.dirname(__file__))  #获取当前爬虫项目的绝对路径
    IMAGES_STORE=os.path.join(project_dir,'images')  #组装新的图片路径
    # IMAGES_STORE = 'D:\ImageSpider'
    

    6、自定义文件管道

    pipelines.py

    import scrapy
    from scrapy.pipelines.files import FilesPipeline
    
    class Mp3Pipeline(FilesPipeline):
        '''自定义管道'''
    
        def get_media_requests(self, item, info):
            # 循环每一首歌地址下载,若传过来的不是集合则无需循环直接yield
            for music,name in zip(item['music_urls'],item['music_names']):
                # 将 img_names值通过meta传到后面
                yield scrapy.Request(music, meta={'title': item['music_title'],'name':name})
    
        def file_path(self, request, response=None, info=None):
            title = request.meta['title']
            name = request.meta['name']
            filename = u'{0}/{1}.mp3'.format(title, name)
            return filename
    

    settings.py

    # Configure item pipelines
    # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    ITEM_PIPELINES = {
       # 'LuoWang.pipelines.LuowangPipeline': 300,
        'LuoWang.pipelines.Mp3Pipeline': 300,
    }
    import os
    #配置保存本地的地址
    project_dir=os.path.abspath(os.path.dirname(__file__))  #获取当前爬虫项目的绝对路径
    FILES_STORE=os.path.join(project_dir,'落网音乐')  #组装新的文件路径
    # FILES_STORE = 'D:/luowang/'
    

    四、Scrapy shell

    1、启动 Scrapy shell

    scrapy shell [option][url|file]

    命令行输入:

    scrapy shell http://httpbin.org/get
    

    2、设置 shell

    Scrapy 的shell是基于运行环境中的python 解释器shell
    本质上就是通过命令调用shell,并在启动的时候预定义需要使用的对象
    scrapy允许通过在项目配置文件”scrapy.cfg”中进行配置来指定解释器shell

    # 例如:
    [settings]
    shell = ipython
    
    [settings]
    default = login_spider.settings
    shell = ipython
    
    [deploy]
    #url = http://localhost:6800/
    project = login_spider
    

    3、shell的使用

    Scrapy shell 本质上就是个普通的python shell
    只不过提供了一些需要使用的对象,快捷方法便于我们调试。

    快捷方法:

    shelp() # 打印可用的对象和方法
    fetch(url[,redirect=True])  # 爬取新的 URL 并更新相关对象
    fetch(request)  # 通过 request 爬取,并更新相关对象
    view(response)  # 使用本地浏览器打开爬取的页面
    scrapy 对象:
    crawler # Crawler 对象
    spider  # 爬取使用的 spider
    request # 请求
    response    # 响应
    settings    # 设置
    

    实例

    $ scrapy shell 'http://scrapy.org' --nolog
    
    [s] Available Scrapy objects:
    [s]  scrapy    scrapy module (contains scrapy.Request, scrapy.Selector, etc)
    [s]  crawler    <scrapy.crawler.Crawler object at 0x7f4e2fb915f8>
    [s]  item      {}
    [s]  request    <GET http://scrapy.org>
    [s]  response  <200 https://scrapy.org/>
    [s]  settings  <scrapy.settings.Settings object at 0x7f4e2e0179e8>
    [s]  spider    <DefaultSpider 'default' at 0x7f4e2dbf98d0>
    [s] Useful shortcuts:
    [s]  fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
    [s]  fetch(req)                  Fetch a scrapy.Request and update local objects 
    [s]  shelp()          Shell help (print this help)
    [s]  view(response)    View response in a browser
    
    In [1]: response.xpath('//title/text()').extract_first()
    Out[1]: 'Scrapy | A Fast and Powerful Scraping and Web Crawling Framework'
    
    In [2]: fetch("http://reddit.com")
    
    In [3]: response.xpath('//title/text()').extract()
    Out[3]: ['reddit: the front page of the internet']
    
    In [4]: request = request.replace(method="POST")
    
    In [5]: fetch(request)
    
    In [6]: response.status
    Out[6]: 404
    

    4、在 spider 内调用 shell

    使用 scrapy.shell.inspect_response 函数:

    import scrapy
    
    
    class MySpider(scrapy.Spider):
        name = "myspider"
        start_urls = [
            "http://example.com",
            "http://example.org",
            "http://example.net",
        ]
    
        def parse(self, response):
            # We want to inspect one specific response.
            if ".org" in response.url:
                from scrapy.shell import inspect_response
                inspect_response(response, self)
    
            # Rest of parsing code.
    

    启动爬虫,将会在执行到inspect_response时进入 shell,当处使用完使用Ctrl-D退出 shell,爬虫会恢复运行。

    五、scrapy.Spider

    1、运行流程

    首先生成初始请求以爬取第一个URL,并指定要使用从这些请求下载的响应调用的回调函数。

    在回调函数中,解析响应(网页)并返回,Item对象, Request对象或这些对象的可迭代的dicts。

    最后,从蜘蛛返回的项目通常会持久保存到数据库(在某些项目管道中)或使用Feed导出写入文件。

    在回调函数中,通常使用选择器解析页面内容 (但您也可以使用BeautifulSoup,lxml或您喜欢的任何机制)并使用解析的数据生成item。

    2、详解

    1)name

    spider的名称

    一个字符串,用于定义此蜘蛛的名称。蜘蛛名称是Scrapy如何定位(并实例化)蜘蛛,因此它必须是唯一的。这是最重要的蜘蛛属性,它是必需的

    2)start_urls

    起始urls

    蜘蛛将开始爬取的URL列表。因此,下载的第一页将是此处列出的页面。后续Request将从起始URL中包含的数据连续生成。

    3)customer_settings

    customer_settings 自定义设置

    运行此蜘蛛时将覆盖项目范围的设置。必须将其定义为类属性,因为在实例化之前更新了设置。

    4)logger 日志

    使用Spider创建的Python日志器。您可以使用它来发送日志消息。

    5)from_crawler

    创建spider的类方法

    这是Scrapy用于创建spider的类方法。一般不用覆盖。

    6)start_requests

    开始请求

    此方法必须返回一个iterable,其中包含第一个要爬网的请求。它只会被调用一次

    7) parse(response)

    默认回调函数

    这是Scrapy在其请求未指定回调时处理下载的响应时使用的默认回调

    8) close

    关闭spider

    spider关闭时调用

    六、CrawlSpider

    1、创建CrawlSpider

    scrapy genspider -t crawl hr.tencent hr.tencent.com

    url 就是你想要爬取的网址
    注意:分析本地文件是一定要带上路径,scrapy shell默认当作url

    scrapy genspider -t crawl mycrawlspider hr.tencent.com
    
    import scrapy
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider, Rule
    
    
    class MycrawlspiderSpider(CrawlSpider):
        name = 'mycrawlspider'
        allowed_domains = ['www']
        start_urls = ['http://www/']
    
        rules = (
            Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
        )
    
        def parse_item(self, response):
            item = {}
            #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
            #item['name'] = response.xpath('//div[@id="name"]').get()
            #item['description'] = response.xpath('//div[@id="description"]').get()
            return item
    

    2、Rule

    Rule用来定义CrawlSpider的爬取规则

    参数:
    link_extractor  Link Extractor对象,它定义如何从每个已爬网页面中提取链接。
    callback  回调函数
    cb_kwargs  是一个包含要传递给回调函数的关键字参数的dict
    follow 它指定是否应该从使用此规则提取的每个响应中跟踪链接。
    process_links  用于过滤连接的回调函数
    process_request  用于过滤请求的额回调函数
    

    3、LinkExtractor

    LinkExractor也是scrapy框架定义的一个类
    它唯一的目的是从web页面中提取最终将被跟踪的额连接。

    我们也可定义我们自己的链接提取器,只需要提供一个名为

    extract_links的方法,它接收Response对象
    并返回scrapy.link.Link对象列表。

    七、CrawlSpider url去重

    八、Scrapy url去重

    九、Request

    1、Scrapy.http.Request

    Scrapy.http.Request类是scrapy框架中request的基类。它的参数如下:
    url(字符串) - 此请求的URL
    callback(callable)- 回调函数
    method(string) - 此请求的HTTP方法。默认为'GET'。
    meta(dict) - Request.meta属性的初始值。
    body(str 或unicode) - 请求体。如果没有传参,默认为空字符串。
    headers(dict) - 此请求的请求头。
    cookies - 请求cookie。
    encoding(字符串) - 此请求的编码(默认为'utf-8')此编码将用于对URL进行百分比编码并将body转换为str(如果给定unicode)。
    priority(int) - 此请求的优先级(默认为0)。
    dont_filter(boolean) - 表示调度程序不应过滤此请求。
    errback(callable) - 在处理请求时引发任何异常时将调用的函数。
    flags(list) - 发送给请求的标志,可用于日志记录或类似目的。
    

    2、属性和方法

    url 包含此请求的URL的字符串。该属性是只读的。更改请求使用的URL replace()。
    method  表示请求中的HTTP方法的字符串。
    headers 类似字典的对象,包含请求头。
    body 包含请求正文的str。该属性是只读的。更改请求使用的URL replace()。
    meta 包含此请求的任意元数据的字典。
    copy() 返回一个新的请求,改请求是此请求的副本。
    replace([ URL,method,headers,body,cookies,meta,encoding,dont_filter,callback,errback] ) 返回一个更新对的request
    

    3、利用request.meta传递参数

    4、FormRequest

    get请求和post请求是最常见的请求。scrapy框架内置了一个FormRequest类
    它扩展了基类Request,具有处理HTML表单的功能。
    它使用lxml.html表单,来预先填充表单字段,其中包含来自Response对象的表单数据。
    

    5、from_response()

    参数:
    response(Responseobject) - 包含HTML表单的响应
    formname(string) - 如果给定,将使用name属性设置为此值的表单。
    formid(string) - 如果给定,将使用id属性设置为此值的表单。
    formxpath(string) - 如果给定,将使用与xpath匹配的第一个表单。
    formcss(string) - 如果给定,将使用与css选择器匹配的第一个表单。
    formnumber(整数) - 当响应包含多个表单时要使用的表单数。
    formdata(dict) - 要在表单数据中覆盖的字段。。
    clickdata(dict) - 用于查找单击控件的属性。
    dont_click(boolean) - 如果为True,将提交表单数据而不单击任何元素。
    

    十、Response

    参数:
    url(字符串) - 此响应的URL
    status(整数) - 响应的HTTP状态。默认为200。
    headers(dict) - 此响应的响应头。dict值可以是字符串(对于单值标头)或列表(对于多值标头)。
    body(字节) - 响应主体。要将解码后的文本作为str(Python 2中的unicode)访问,您可以使用response.text来自编码感知的 Response子类,例如TextResponse。
    flags(列表) - 是包含Response.flags属性初始值的列表 。如果给定,列表将被浅层复制。
    request(Requestobject) - Response.request属性的初始值。这表示Request生成此响应的内容。
    
    属性和方法:
    url
    status
    headers
    body
    request
    meta
    flags
    copy()
    replace([ url,status,headers,body,request,flags,cls ] )
    urljoin(url )
    follow(url)
    

    十一、日志配置和使用

    Scrapy logger 在每个Spider实例中提供了一个可以访问和使用的实例,使用方法,见下图
    
    当然可以通过python的logging来记录。
    比如:logging.warning('This is a warning!')
    
    但是为了后期维护方面,我们可以创建不同的记录器来封装消息。
    
    并且使用组件或函数的名称进行命名,见下图案例:
    
    这些设置可用于配置日志记录:
    
    LOG_FILE        日志输出文件,如果为None,就打印在控制台
    LOG_ENABLED 是否启用日志,默认True
    LOG_ENCODING    日期编码,默认utf-8
    LOG_LEVEL   日志等级,默认debug
    LOG_FORMAT  日志格式
    LOG_DATEFORMAT  日志日期格式
    LOG_STDOUT  日志标准输出,默认False,如果True所有标准输出都将写入日志中
    LOG_SHORT_NAMES   短日志名,默认为False,如果True将不输出组件名
    
    项目中一般设置:
    LOG_FILE = 'logfile_name'
    LOG_LEVEL = 'INFO'
    

    十二、模拟登陆

    分析

    捕捉获取登陆时需要上传的form,认为构造formdata,使用FormRequest请求

    # -*- coding: utf-8 -*-
    import scrapy
    
    
    class MyLoginSpiderSpider(scrapy.Spider):
        name = 'my_login_spider'
        # allowed_domains = ['www']
        start_urls = ['http://example.webscraping.com/places/default/user/login']
    
        def parse(self, response):
            data = {
                'email':'570454176@qq.com',
                'password':'12345678'
            }
            data['_next'] = response.xpath('//input[@name="_next"]/@value').extract_first()
            data['_formkey'] = response.xpath('//input[@name="_formkey"]/@value').extract_first()
            data['_formname'] = response.xpath('//input[@name="_formname"]/@value').extract_first()
            # print(data)
            # return scrapy.Request(
                                    url='http://example.webscraping.com/places/default/user/login',
                                    method='POST',
                                    meta=data,
                                    callback=self.detail_parse)
            yield scrapy.FormRequest(
                                    url='http://example.webscraping.com/places/default/user/login',
                                    formdata=data,
                                    callback=self.detail_parse)
            # pass
            
        def detail_parse(self,response):
            # print(response.body)
            login_msg = response.xpath('//div[@class="flash"]/text()').extract_first()
            if login_msg == 'Logged in':
                print('模拟登陆成功')
            else:
                print('模拟登陆失败')
            # pass
    

    十三、下载中间件

    下载中间件是一个用来hooks进Scrapy的request/response处理过程的框架。
    它是一个轻量级的底层系统,用来全局修改scrapy的request和response。

    scrapy框架中的下载中间件,是实现了特殊方法的类。

    scrapy系统自带的中间件被放在DOWNLOADER_MIDDLEWARES_BASE设置中

    用户自定义的中间件需要在DOWNLOADER_MIDDLEWARES中进行设置
    改设置是一个dict,键是中间件类路径,期值是中间件的顺序,是一个正整数0-1000.越小越靠近引擎。

    1、API

    process_request(request,spider) 处理请求,对于通过中间件的每个请求调用此方法 请求前

    返回None---scrapy 直接返回这个Request
    返回Response---scrapy 直接返回这个Response
    返回Request ---scrapy  重新调度返回的Request请求
    返回异常  ---scrapy 调用 process_exception
    

    process_response(request, response, spider) 处理响应,对于通过中间件的每个响应,调用此方法 请求后

    process_exception(request, exception, spider) 处理请求时发生了异常调用

    from_crawler(cls,crawler )

    2、内置下载中间件

    常用内置中间件:
    CookieMiddleware        支持cookie,通过设置COOKIES_ENABLED 来开启和关闭
    
    HttpProxyMiddleware HTTP代理,通过设置request.meta['proxy']的值来设置
    
    UserAgentMiddleware 与用户代理中间件。
    

    3、下载中间件的使用

    用户代理池

    # 定义代理池
    USER_AGENT =[
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3641.400 QQBrowser/10.4.3284.400",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3641.400 QQBrowser/10.4.3284.400",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3641.400 QQBrowser/10.4.3284.400",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3641.400 QQBrowser/10.4.3284.400"
    ]
    import random
    class UserAgentMiddleware(object):
            # 用户代理中间件
        def process_request(self,request,spider):
            '''
            对request添加cookies信息
            :param request:
            :param spider:
            :return:
            '''
            # 在USER_AGENT中随机一个代理
            request.headers['User-Agent'] = random.choice(USER_AGENT)
            print(request.headers,'=================')
    
        def process_response(self,request,response,spider):
            if response.status ==403:
                print('请求失败...')
                return request
            return response
    

    十四、scrapy 常用设置

    1、设置优先级

    命令行选项(优先级最高)
    设置per-spider
    项目设置模块
    各命令默认设置
    默认全局设置(低优先级)

    如下:

    # 项目名
    BOT_NAME = 'Baidu'
    # 项目路径
    SPIDER_MODULES = ['Baidu.spiders']
    NEWSPIDER_MODULE = 'Baidu.spiders'
    
    # 用户代理
    # Crawl responsibly by identifying yourself (and your website) on the user-agent
    #USER_AGENT = 'Baidu (+http://www.yourdomain.com)'
    
    # 君子协议
    # Obey robots.txt rules
    ROBOTSTXT_OBEY = False
    
    # 最大并发值
    # Configure maximum concurrent requests performed by Scrapy (default: 16)
    #CONCURRENT_REQUESTS = 32
    
    # item处理最大并发数,默认100
    CONCURRENT_ITEMS            
    # 下载最大并发数
    CONCURRENT_REQUESTS     
    # 单个域名最大并发数
    CONCURRENT_REQUESTS_PER_DOMAIN  
    # 单个ip最大并发数
    CONCURRENT_REQUESTS_PER_IP  
    
    # 请求延时
    # Configure a delay for requests for the same website (default: 0)
    # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay
    # See also autothrottle settings and docs
    #DOWNLOAD_DELAY = 3
    
    # 禁用COOKIES 
    # Disable cookies (enabled by default)
    #COOKIES_ENABLED = False
    
    # HEADERS请求头
    # Override the default request headers:
    #DEFAULT_REQUEST_HEADERS = {
    #   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    #   'Accept-Language': 'en',
    #}
    
    # 下载中间件
    # Enable or disable downloader middlewares
    # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
    DOWNLOADER_MIDDLEWARES = {
        'Baidu.middlewares.BaiduDownloaderMiddleware': 543,
            'Baidu.middlewares.UserAgentMiddleware': 543,
    }
    
    # Pipeline 管道
    # Configure item pipelines
    # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    #ITEM_PIPELINES = {
    #    'Baidu.pipelines.BaiduPipeline': 300,
    #}
    

    十五、Scrapy对接Selenium

    chrome的webdriver: http://chromedriver.storage.googleapis.com/index.html

    Firefox Firefox驱动下载地址为:https://github.com/mozilla/geckodriver/releases/

    IE浏览器驱动下载地址为:http://selenium-release.storage.googleapis.com/index.html (不推荐,没人用)

    根据操作系统,以及浏览器版本,下载相应的驱动

    并且将下载的webdriver的路径设置到环境变量中

    1、Selenium的使用

    # 导入模块
    from selenium import webdriver
    import time
    
    # 模拟调用Chrome浏览器
    drvier = webdriver.Chrome()
    # 访问网站
    drvier.get('https://www.baidu.com')
    
    # 延时5s
    time.sleep(5)
    
    # 获取js渲染之后的数据
    print(drvier.page_source)
    

    2、使用中间件

    from selenium import webdriver
    import time
    import scrapy
    
    class UserAgentMiddleware(object):
        def process_request(self, request, spider):
            # 打开Chrome浏览器
            self.driver = webdriver.Chrome()
            # 打开相应的网站
            self.driver.get(request.url)
            # 延时
            time.sleep(5)
            # 获取js渲染后的内容
            html = self.driver.page_source
            # 关闭driver
            self.driver.quit()
            # 返回Response对象
            return scrapy.http.HtmlResponse(url=request.url,body=html,encoding='utf-8',request=request)
    

    十六、Scrapy项目部署

    1、scrapyd

    Scrapyd是一个运行Scrapy spider的开源应用程序。它提供了一个带有HTTP API的服务器,能够运行和监控Scrapy蜘蛛。要将spider部署到Scrapyd,可以使用由Scrapyd客户端包提供的Scrapyd -deploy工具。
    Scrapyd安装
    Scrapyd依赖于以下库,但安装过程负责安装缺少的库:
    
    Python2.6以上
    Twisted8.0以上
    Scrapy0.17以上
    如何安装Scrapy取决于您正在使用的平台。通用的方法是从PyPI安装它:
        pip  install  scrapyd
    安装之后 通过scrapyd命令启动即可:scrapyd
    scrapyd带有一个最小的Web界面,启动后,通过访问http://localhost:6800。如左图:
    

    2、部署流程

    命令:scrapyd 启动一个web服务
    访问:127.0.0.1:6800 http://192.168.32.129:6800/

    在本地不能打开127.0.0.1:6800网页,需要配置端口转发:6800 修改配置文件 0.0.0.0

    进入到目录:cd /usr/local/lib/python3.6/dist-packages/scrapyd
    进入文件:sudo vim default_scrapyd.conf
    修改 bind_address=127.0.0.1 修改为0.0.0.0

    第一步:启动scrapyd
    第二步:修改scrapy.cfg文件
    [settings]
    default = DownloadImage.settings

    ​ [deploy]
    url = http://127.0.0.1:6800/ # scrapyd 服务器地址
    project = DownloadImage
    第三步:上传 scrapyd-deploy <target> -p <projectname>
    第四步:启动 curl http://localhost:6800/schedule.json -d project=<projectname> -d spider=<spidername>
    第五步:停止爬虫 curl http://localhost:6800/cancel.json -d project=tutorial -d job=4fc26e4209da11e9b344000c292b839

    3、API

    上传

    scrapyd-deploy <target> -p <projectname>
    例子:scrapyd-deploy -p DownloadImage
    

    启动

    curl http://localhost:6800/schedule.json -d project=<projectname> -d spider=<spidername>
    

    停止

    curl http://localhost:6800/cancel.json -d project=<projectname> -d <spidername> job=jobid
    

    删除项目

    curl http://localhost:6800/delproject.json -d project=<projectname>
    

    列出项目

    curl http://localhost:6800/listproject.json
    

    列出爬虫

    curl http://localhost:6800/listspider.json?project=myproject
    

    官方文档

    https://scrapyd.readthedocs.io/en/latest/api.html

    scrapyd设置

    Scrapyd在以下位置搜索配置文件,并按顺序解析它们,最新的配置文件具有更高的优先级:
    
    /etc/scrapyd/scrapyd.conf (Unix)
    c:\scrapyd\scrapyd.conf (Windows)
    /etc/scrapyd/conf.d/* (in alphabetical order, Unix)
    scrapyd.conf
    ~/.scrapyd.conf (users home directory)
    

    scrapyd部署

    使用官方提供的工具scrapyd 分为服务端和客户端

    在测试服务器上开启scrapyd服务

    在客户端 通过scrapy-client 上传本地的代码到服务端

    4、window下部署

    python absolute_dir/scrapyd-deploy -p <projectname>
    

    十七、scrapy-redis

    scrapy-redis是scrapy框架基于redis数据库的组件,用于scrapy项目的分布式开发和部署。

    特征:分布式爬取
    您可以启动多个spider工程,相互之间共享单个redis的requests队列。最适合广泛的多个域名网站的内容爬取。

    分布式数据处理
    爬取到的scrapy的item数据可以推入到redis队列中,这意味着你可以根据需求启动尽可能多的处理程序来共享item的队列,进行item数据持久化处理

    Scrapy即插即用组件
    Scheduler调度器 + Duplication复制 过滤器,Item Pipeline,基本spider

    1、request请求共享

    首先Slaver端从Master端拿任务(Request、url)进行数据抓取,Slaver抓取数据的同时,产生新任务的Request便提交给 Master 处理;

    Master端只有一个Redis数据库,负责将未处理的Request去重和任务分配,将处理后的Request加入待爬队列,并且存储爬取的数据。

    Scrapy-Redis默认使用的就是这种策略,我们实现起来很简单,因为任务调度等工作Scrapy-Redis都已经帮我们做好了,我们只需要继承RedisSpider、指定redis_key就行了。

    缺点是,Scrapy-Redis调度的任务是Request对象,里面信息量比较大(不仅包含url,还有callback函数、headers等信息),可能导致的结果就是会降低爬虫速度、而且会占用Redis大量的存储空间,所以如果要保证效率,那么就需要一定硬件水平。

    2、安装

    通过pip 安装: pip install scrapy-redis

    官方文档:https://scrapy-redis.readthedocs.io/en/stable/

    源码位置:https://github.com/rmax/scrapy-redis

    博客:https://www.cnblogs.com/kylinlin/p/5198233.html

    3、配置文件

    1(必须). 使用了scrapy_redis的去重组件,在redis数据库里做去重

    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    

    2(必须). 使用了scrapy_redis的调度器,在redis里分配请求

    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    

    3(可选). 在redis中保持scrapy-redis用到的各个队列,从而True允许暂停和暂停后恢复,也就是不清理redis queues

    SCHEDULER_PERSIST = True
    

    4(必须). 通过配置RedisPipeline将item写入key为 spider.name : items 的redis的list中,供后面的分布式处理item
    这个已经由 scrapy-redis 实现,不需要我们写代码,直接使用即可

    ITEM_PIPELINES = {
        'scrapy_redis.pipelines.RedisPipeline': 100
    }
    

    5(必须). 指定redis数据库的连接参数

    REDIS_HOST = '127.0.0.1'
    REDIS_PORT = 6379
    

    4、redis键名介绍

    1、 “项目名:items”
    list 类型,保存爬虫获取到的数据item
    内容是 json 字符串

    2、 “项目名:dupefilter”
    set类型,用于爬虫访问的URL去重
    内容是 40个字符的 url 的hash字符串

    3、 “项目名: start_urls”
    List 类型,用于获取spider启动时爬取的第一个url

    4、 “项目名:requests”
    zset类型,用于scheduler调度处理 requests
    内容是 request 对象的序列化 字符串

    十八、分布式爬虫

    scrapy-redis 改写爬虫

    1、dlimg_spider.py

    修改爬虫文件 dlimg_spider.py

    from scrapy_redis.spiders import RedisSpider
    
        class DlimgSpiderSpider(RedisSpider):
            name = 'dlimg_spider'
            # allowed_domains = ['sss']
            # start_urls = ['http://lab.scrapyd.cn/archives/55.html', 'http://lab.scrapyd.cn/archives/57.html']
            redis_key = 'DownloadImage:start_url'
    

    2、settings.py

    修改爬虫文件 settings.py

    # scrapy_redis 去重
    DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupefilter'
    
    # scrapy_redis的调度器
    SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
    
    # 保持队列 允许暂停和恢复
    SCHEDULER_PERSIST = True
    
    # redis的配置
    REDIS_HOST = '127.0.0.1'
    
    REDIS_PORT = 6379
    
    ITEM_PIPELINES = {
        # redis的Pipeline,尽量不要把数据存到redis,会让服务器卡
       'scrapy_redis.pipelines.RedisPipeline':400,
       # 'DownloadImage.pipelines.DownloadimagePipeline': 300,
    }
    

    3、运行爬虫

    在不同的机器上运行此爬虫

    4、键入start_url

    通过redis数据库输入start_url

    lpush DownloadImage:start_url + start_url
    

    相关文章

      网友评论

          本文标题:06 scrapy框架

          本文链接:https://www.haomeiwen.com/subject/qetbdctx.html