zoukankan      html  css  js  c++  java
  • Scrapy框架简介及小项目应用

    今天来总结一下Scrapy框架的用法。scrapy的架构如下:

      

    Engine  :引擎,处理整个系统的数据流处理、触发事务,是整个框架的核心。

    Items :项目,它定义了爬取结果的数据结构,爬取的数据会被赋值成该 Items 对象。

    Scheduler  :调度器,接受 Engine 发过来的请求,并将其加入队列中,在 Engine 再次请求的时候将请求提供给 Engine。

    Downloader  :下载器,下载网页内容,并将网页容返回给 Spiders。

    Spiders : 蜘蛛,其内定义了爬取的逻辑和网页 解析规则 ,它主要负责解析响应并生成提取结果和新的请求。

    ItemPipeline  :项目管道,负责处理由 Spiders 从网页中提取的项目,它的主要任务是清洗、验证和存储数据。

    Downloader Middlewares  :下载器中间件,主要处理 Engine与 Downloader 之间的请求及响应。

    Spide Middlewares  : Spiders 中间件,主要处理 Spiders 输入的响应和输出的结果,及新的请求。

    接下来介绍 个简单的项目,完成一遍 Scrapy抓取流程

    1、打开 cmd 终端窗口, 输入 scrapy startproject abcd,生成一个 abcd 的项目

    2、按照提示,输入 cd abcd 进入 abcd 项目所在的文件夹, 输入 scrapy genspider quotes quotes.toscrape.com,

      quotes是 spiders 的 .py 文件,quotes.toscrape.com 是爬取的网站域名。

       

    打开项目文件 quotes,里面包含内容如下:

    allowed domains :它是允许爬取的域名,如果初始或后续的请求链接不是这个域名下的,则请求链接会被过滤掉

    start_urls :它包含了 Spider 在启动时爬取的 url 列表,初始请求是由它来定义的

    3、观察目标网站,我们可以获取到到内容有 text 、author、 tags,因此开始定义 Items.py

    class AbcdItem(scrapy.Item):
        # define the fields for your item here like:
        text = scrapy.Field()
        author = scrapy.Field()
        tags = scrapy.Field()

    4、进入quotes.py文件,在 parse函数下输入 print(response.text), 在终端输入 scrapy crawl quotes,看看能否正常请求到内容

      结果报错:UnicodeEncodeError: 'gbk' codec can't encode character '❤' in position 11162: illegal multibyte sequence

      是说编码错误,经过查资料,进行修改就改好了,https://blog.csdn.net/u013155359/article/details/81566807

    import io  
    import sys 
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gbk')

    说是因为编码问题,但我还不太理解原因,暂且这么用

    5、接下来进行quotes.py代码编写

        def parse(self, response):
            quotes = response.css('.quote')
            for quote in quotes:
                item = AbcdItem()
                item['text'] = quote.css('.text::text').extract_first()
                item['author'] = quote.css('.author::text').extract_first()
                item['tags'] = quote.css('.tags .tag::text').extract()
                yield item

    终端运行,得到正确的输出

    6、抓取下一页的内容

        def parse(self, response):
            quotes = response.css('.quote')  # response 直接就是返回的内容
            for quote in quotes:
                item = QuoteItem()
                text = quote.css('.text::text').extract_first()
                author = quote.css('.author::text').extract_first()
                tags = quote.css('.tags .tag::text').extract()
                item['text'] = text
                item['author'] = author
                item['tags'] = tags
                yield item
            next = response.css('.pager .next a::attr(href)').extract_first()
            url = response.urljoin(next)  # 获取一个绝对的URL
            yield scrapy.Request(url=url, callback=self.parse)
    url = response.urljoin(next),获取一个绝对的 URL,next='page/2/',url='http://quotes.toscrape.com/page/2/yield scrapy.Request(url=url, callback=self.parse),重新调用 parse()函数,一直循环下去,运行结果正常输出所有内容。
    7、将输出的内容保存下来,有一下四种方法,个人感觉保存为 json 或 jl 格式的文件看起来最清晰。
      scrapy crawl quotes -o quotes.json
      scrapy crawl quotes -o quotes.jl
      scrapy crawl quotes -o quotes.xml 
      scrapy crawl quotes -o quotes.csv
    8、保存到MongoDb数据库,这个稍微复杂一点,需要用到 Pipeline.py 文件。
      先在 Pipeline.py 中写入以下代码:
    import pymongo
    from scrapy.exceptions import DropItem
    
    class TextPipeline(object):
        def __init__(self):
            self.limit = 50
        def process_item(self, item, spider):
            if item['text']:
                if len(item['text']) > self.limit:    # 对长度大于50的text进行修改
                    item['text'] = item['text'][0:self.limit].rstrip()+'...'
                return item
            else:
                return DropItem('Missing Text')
    
    class MongoPipeline(object):
        def __init__(self, mongo_uri, mongo_db):
            self.mongo_uri = mongo_uri
            self.mongo_db = mongo_db
    
        @classmethod
        def from_crawler(cls, crawler):
            return cls(
                mongo_uri=crawler.settings.get('MONGO_URI'),
                mongo_db=crawler.settings.get('MONGO_DB')
            )
    
        def open_spider(self, spider):
            self.client = pymongo.MongoClient(self.mongo_uri)
            self.db = self.client[self.mongo_db]
    
        def process_item(self, item, spider):
            name = item.__class__.__name__
            self.db[name].insert(dict(item))
            return item
    
        def close_spider(self, spider):
            self.client.close()
    
    

    定义了 TextPipeline() 和 MongoPipeline() 两个类。

    TextPipeline() 和 MongoPipeline() 两个类都有 process_item 的方法,process item ()方法必须返回包含数据的字典或 Item 象,或者抛出 Dropltem 异常,

    启用 Item Pipeline 后, Item Pipeline 会自动调用这个方法。

    MondoPipeline() 类: from crawler(),通过 crawler 我们可以拿到全局配置的每个配置信息,这个方法的定义主要是用来获取 settings.py 中的配置

                open spider(), Spider 开启时,这个方法被调用

                close_spider(), Spider 关闭时,这个方法会调用

                process item () 方法则执行了数据插入操作

     我们在 settings.py 中加入如下内容

    MONGO_URI='localhost'
    MONGO_DB = 'abcd'
    
    ITEM_PIPELINES = {
        'abcd.pipelines.TextPipeline': 300,
        'abcd.pipelines.MongoPipeline': 400
    }

    在终端运行 scrapy crawl quotes,数据成功在 MongoDb 中保存下来

     


     

     

  • 相关阅读:
    获取单选框的值
    HTML5本地存储详解
    设为首页和加入收藏
    用PhotoSwipe制作相册,手势可放大
    iOS 加载本地 HTML 文件 CSS 样式图片无效果
    PhotoSwipe简介
    Flexslider图片轮播、文字图片相结合滑动切换效果
    网页中插入视频的方法----腾讯、优酷为例
    webapp在Android中点击链接的时候会有淡蓝色的遮罩层
    C# 获取北京时间 (根据纪元时间(1970/1/1)转换为DateTime)
  • 原文地址:https://www.cnblogs.com/zhangguoxv/p/10091760.html
Copyright © 2011-2022 走看看