爬虫框架Scrapy

结构

Scrapy由以下几部分组成:

  • Scrapy Engine:引擎,负责各个部件之间的调度、通信、数据传递等。我的理解是可以理解为一个调用各个程序的操作面板。
  • Scheduler:调度器,接收引擎发来的Request请求,按照一定规则进入队列,返回给引擎
  • Downloader:下载器,负责下载引擎发送的Request,然后把获取的Response交给引擎,然后引擎交给Spider处理
  • Spider:爬虫,定义请求的url等信息,以及对数据的处理
  • Item Pipeline:数据管道,爬虫中获取到的数据会放入数据管道,然后在数据管道中进行处理。比如保存到硬盘

此外还有一些中间件,有一些扩展功能

运作流程

在这里插入图片描述

  1. Spider告诉引擎我要做啥,然后引擎安排给Schedule
  2. Schedule安排发送请求给某网站
  3. 网站的Response拿到后通过引擎回复给Spider
  4. Spider把数据处理后放入数据管道

使用步骤

制作一个Scrapy爬虫需要以下几步

  1. 新建项目(scrapy startproject pj_name):新建一个项目
  2. 编写items.py:明确需要抓取哪些数据
  3. 制作Spiders:修改xxspider.py,描述如何获取想要的数据
  4. 存储内容:修改pipelines.py,设计如何保存数据

安装

在cmd下用如下命令安装

pip install scrapy

在命令行中首先cd到项目保存目录,然后使用scrapy命令创建名为mydemo的项目

scrapy startproject demo

cd到mydemo目录,用下面的命令创建名为douban的蜘蛛程序。

scrapy genspider douban movie.douban.com

例子1:爬取豆瓣电影 Top250 电影标题、评分和金句的爬虫

  1. items.pyItem类中定义字段,这些字段用来保存数据

    import scrapy
    
    class DoubanItem(scrapy.Item):
        title = scrapy.Field()
        score = scrapy.Field()
        motto = scrapy.Field()
    
  2. 修改spiders文件夹中名为douban.py 的文件,它是蜘蛛程序的核心,需要我们添加解析页面的代码。在这里,我们可以通过对Response对象的解析,获取电影的信息,代码如下所示。

    import scrapy
    from scrapy import Selector, Request
    from scrapy.http import HtmlResponse
    
    from mydemo.items import DoubanItem
    
    class DoubanSpider(scrapy.Spider):
        name = 'douban'
        allowed_domains = ['movie.douban.com']
    
        def start_requests(self):
            for page in range(10):
                yield Request(url=f'https://movie.douban.com/top250?start={page * 25}')
    
        def parse(self, response: HtmlResponse):
            sel = Selector(response)
            movie_items = sel.css('#content > div > div.article > ol > li')
            for movie_sel in movie_items:
                item = DoubanItem()
                item['title'] = movie_sel.css('.title::text').extract_first()
                item['score'] = movie_sel.css('.rating_num::text').extract_first()
                item['motto'] = movie_sel.css('.inq::text').extract_first()
                yield item
    
  3. 将爬取结果保存到Excel中,修改pipelines.py

    import openpyxl
    from mydemo.items import DoubanItem
    
    class DoubanItemPipeline:
    
        def __init__(self):
            self.wb = openpyxl.Workbook()
            self.sheet = self.wb.active
            self.sheet.title = 'Top250'
            self.sheet.append(('名称', '评分', '名言'))
    
        def process_item(self, item: DoubanItem, spider):
            self.sheet.append((item['title'], item['score'], item['motto']))
            return item
    
        def close_spider(self, spider):
            self.wb.save('output/豆瓣电影数据.xlsx')
    
  4. 修改settings.py,主要修改以下几个参数

    BOT_NAME = "mydemo"
    
    SPIDER_MODULES = ["mydemo.spiders"]
    NEWSPIDER_MODULE = "mydemo.spiders"
    
    # Crawl responsibly by identifying yourself (and your website) on the user-agent
    USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) " \
                 "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"
    
    # 是否遵守爬虫协议
    ROBOTSTXT_OBEY = True
    
    # 并发请求数
    CONCURRENT_REQUESTS = 8
    
    # 配置数据管道
    # See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
    ITEM_PIPELINES = {
       "mydemo.pipelines.DoubanItemPipeline": 300,
    }
    

运行

scrapy crawl douban

实践:爬取Pixiv周榜的标题、作者等信息

  1. 用如下命令新建spider

    scrapy genspider pixiv www.pixiv.net
    

    可以看到在spiders/目录下新建了pixiv.py

  2. 修改主目录的items.py,添加如下类。这里每个字段就代表了要保存的数据

    class PixivItem(scrapy.Item):
        title = scrapy.Field()
        user_name = scrapy.Field()
        p_id = scrapy.Field()
        re_url = scrapy.Field()
    
  3. 修改pixiv.py,注意在custom_settings中指定数据管道

    import scrapy
    from scrapy import Request
    
    class PixivSpider(scrapy.Spider):
        name = "pixiv"
        allowed_domains = ["www.pixiv.net"]
        start_urls = ["https://www.pixiv.net"]
        custom_settings = {
            'ITEM_PIPELINES': {
                # 如果有多条数据管道,需要在这里指定
                'mydemo.pipelines.PixivPipeline': 400,
            }
        }
    
        def start_requests(self):
            for page in range(1, 6):
                yield Request(url=f"https://www.pixiv.net/ranking.php?mode=weekly&p={page}&format=json")
    
        def parse(self, response, **kwargs):
            """parse 在 Scrapy 会在 Spider 启动后自动调用,用于处理抓取的网页数据。
            """
            datas = response.json()["contents"]
            for data in datas:
                yield {
                    "title": data["title"],
                    "user_name": data["user_name"],
                    "p_id": data["illust_id"],
                    "re_url": f"https://www.pixiv.net/artworks/{data['illust_id']}"
                }
    
  4. 在主目录的piplines.py中,添加数据管道PixivPipeline

    class PixivPipeline:
    
        def __init__(self):
            self.wb = openpyxl.Workbook()
            self.sheet = self.wb.active
            self.sheet.title = 'weekly'
            self.sheet.append(('标题', '作者', 'P_ID', "链接"))
    
        def process_item(self, item: PixivItem, spider):
            self.sheet.append((item['title'], item['user_name'], item['p_id'], item['re_url']))
            return item
    
        def close_spider(self, spider):
            # 获取根目录路径
            root_path = os.path.abspath(os.path.dirname(__file__))
            self.wb.save(f'{root_path}/output/pixiv_weekly_rank数据.xlsx')
    
  5. 在settings.py中,添加数据管道

    ITEM_PIPELINES = {
        "mydemo.pipelines.DoubanItemPipeline": 300,
        "mydemo.pipelines.PixivPipeline": 400
    }
    

运行

scrapy crawl pixiv

完整项目代码地址:
https://github.com/h-kayotin/mydemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值