深入理解Python分布式爬虫原理

深入理解Python分布式爬虫原理

在分布式爬虫中,一个爬虫任务被分成多个子任务,分发给多个节点执行,最终合并结果。Python分布式爬虫框架Scrapy已经内置了分布式爬虫功能,但是对于特定的需求,我们可能需要自己实现分布式爬虫。

分布式爬虫的原理

分布式爬虫的实现主要依赖于队列和节点间的通信。

节点1从队列中获取爬虫任务,爬取数据后将结果存储到队列中。节点2从队列中获取数据,清洗和处理后再将结果存储到队列中,直到所有子任务完成。最后,节点3从队列中获取所有数据,合并结果并返回给调用方。

实现分布式爬虫的步骤

  1. 安装分布式框架Celery
pip install celery
  1. 定义任务
from celery import Celery

app = Celery('tasks', broker='amqp://guest@localhost//')

@app.task
def crawl(url):
    ...
    return data

利用Celery框架,我们可以轻松地编写分布式爬虫。定义的任务函数需要使用装饰器@celery.task将该函数注册为可以在分布式环境下运行的任务。

  1. 启动工作节点
celery -A tasks worker --loglevel=info

该命令会启动一个工作节点,用于执行我们编写的任务函数。

  1. 发送任务到队列中
from tasks import crawl

urls = [
    'https://www.example.com/1',
    'https://www.example.com/2',
    'https://www.example.com/3',
    ...
]

for url in urls:
    crawl.delay(url)

将任务发送到队列中,任务参数url会被传递到crawl函数中。任务启动后会被工作节点获取并执行。在执行过程中,可以通过Celery提供的监控界面查看任务的执行情况。

示例1:爬取豆瓣电影Top250

1. 爬虫代码

from scrapy import Spider, Request
from scrapy.crawler import CrawlerProcess

class DoubanTopSpider(Spider):
    name = 'douban_top'
    allowed_domains = ['movie.douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        yield from self.parse_movie(response)

        is_last_page = '后页' not in response.css('.next a::text').getall()
        if not is_last_page:
            next_page_url = response.css('.next a::attr(href)').get()
            yield Request(next_page_url, callback=self.parse)

    def parse_movie(self, response):
        for movie in response.css('.grid_view .item'):
            yield {
                'title': movie.css('.title::text').get(),
                'info': movie.css('.bd p::text').get(),
                'rating': movie.css('.rating_num::text').get(),
                'cover': movie.css('img::attr(src)').get(),
            }

process = CrawlerProcess({
    'FEED_FORMAT': 'csv',
    'FEED_URI': 'douban_top250.csv'
})

process.crawl(DoubanTopSpider)
process.start()

该爬虫爬取豆瓣电影Top250的电影名、简介、评分和海报,并将结果以csv格式保存到本地文件douban_top250.csv中。

2. 分布式爬虫代码

from scrapy import Spider, Request
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from celery import Celery

class DoubanTopSpider(Spider):
    name = 'douban_top'
    allowed_domains = ['movie.douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        yield from self.parse_movie(response)

        is_last_page = '后页' not in response.css('.next a::text').getall()
        if not is_last_page:
            next_page_url = response.css('.next a::attr(href)').get()
            yield Request(next_page_url, callback=self.parse)

    def parse_movie(self, response):
        for movie in response.css('.grid_view .item'):
            yield {
                'title': movie.css('.title::text').get(),
                'info': movie.css('.bd p::text').get(),
                'rating': movie.css('.rating_num::text').get(),
                'cover': movie.css('img::attr(src)').get(),
            }

app = Celery('tasks', broker='amqp://guest@localhost//')

@app.task
def crawl(url):
    settings = get_project_settings()
    process = CrawlerProcess(settings)
    process.crawl(DoubanTopSpider)
    process.start()

if __name__ == '__main__':
    urls = [
        'https://movie.douban.com/top250?start=0&filter=',
        'https://movie.douban.com/top250?start=25&filter=',
        'https://movie.douban.com/top250?start=50&filter=',
        ...
    ]

    for url in urls:
        crawl.delay(url)

在分布式爬虫代码中,我们定义了一个名为crawl的任务,并将其绑定到DoubanTopSpider爬虫上。在任务函数中,我们通过get_project_settings函数获取爬虫的配置,创建一个CrawlerProcess对象,然后开始运行DoubanTopSpider爬虫。

运行分布式爬虫代码,它会将豆瓣电影Top250的每一页分发到不同的工作节点上执行,最后将结果合并到本地文件douban_top250.csv中。

示例2:爬取新浪微博关键字

1. 爬虫代码

from scrapy import Spider, Request
from scrapy.crawler import CrawlerProcess
import json

class WeiboTopicSpider(Spider):
    name = 'weibo_topic'
    allowed_domains = ['m.weibo.cn']
    base_url = 'https://m.weibo.cn/api/container/getIndex?type=wb&queryVal={}&since_id={}'
    headers = {
        'Referer': 'https://m.weibo.cn',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }

    def start_requests(self):
        url = self.base_url.format(self.keyword, '')
        yield Request(url, headers=self.headers)

    def parse(self, response):
        data = json.loads(response.text)
        cards = data.get('data', {}).get('cards', [])
        for card in cards:
            mblog = card.get('mblog', {})
            yield {
                'created_at': mblog.get('created_at'),
                'text': mblog.get('text'),
                'attitudes_count': mblog.get('attitudes_count'),
                'comments_count': mblog.get('comments_count'),
                'reposts_count': mblog.get('reposts_count'),
            }

        next_id = data.get('data', {}).get('cardlistInfo', {}).get('since_id')
        if next_id:
            next_url = self.base_url.format(self.keyword, next_id)
            yield Request(next_url, headers=self.headers, callback=self.parse)

process = CrawlerProcess({
    'FEED_FORMAT': 'csv',
    'FEED_URI': 'weibo_topic.csv'
})

process.crawl(WeiboTopicSpider, keyword='Python')
process.start()

该爬虫爬取新浪微博中包含关键字'Python'的微博的文本、发布时间、点赞数、评论数和转发数,并将结果以csv格式保存到本地文件weibo_topic.csv中。

2. 分布式爬虫代码

from scrapy import Spider, Request
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from celery import Celery

class WeiboTopicSpider(Spider):
    name = 'weibo_topic'
    allowed_domains = ['m.weibo.cn']
    base_url = 'https://m.weibo.cn/api/container/getIndex?type=wb&queryVal={}&since_id={}'
    headers = {
        'Referer': 'https://m.weibo.cn',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }

    def start_requests(self):
        url = self.base_url.format(self.keyword, '')
        yield Request(url, headers=self.headers)

    def parse(self, response):
        data = json.loads(response.text)
        cards = data.get('data', {}).get('cards', [])
        for card in cards:
            mblog = card.get('mblog', {})
            yield {
                'created_at': mblog.get('created_at'),
                'text': mblog.get('text'),
                'attitudes_count': mblog.get('attitudes_count'),
                'comments_count': mblog.get('comments_count'),
                'reposts_count': mblog.get('reposts_count'),
            }

        next_id = data.get('data', {}).get('cardlistInfo', {}).get('since_id')
        if next_id:
            next_url = self.base_url.format(self.keyword, next_id)
            yield Request(next_url, headers=self.headers, callback=self.parse)

app = Celery('tasks', broker='amqp://guest@localhost//')

@app.task
def crawl(keyword):
    settings = get_project_settings()
    process = CrawlerProcess(settings)
    process.crawl(WeiboTopicSpider, keyword=keyword)
    process.start()

if __name__ == '__main__':
    keywords = ['Python', '数据挖掘', '人工智能', ...]

    for keyword in keywords:
        crawl.delay(keyword)

在分布式爬虫代码中,我们定义了一个名为crawl的任务,并将其绑定到WeiboTopicSpider爬虫上。在任务函数中,我们通过get_project_settings函数获取爬虫的配置,创建一个CrawlerProcess对象,然后开始运行WeiboTopicSpider爬虫。

运行分布式爬虫代码,它会将每个关键字的爬取任务分发到不同的工作节点上执行,最后将结果合并到本地文件weibo_topic.csv中。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解Python分布式爬虫原理 - Python技术站

(0)
上一篇 2023年5月25日
下一篇 2023年5月25日

相关文章

  • 解决Devc++运行窗口中文乱码的实现步骤

    那么下面就给大家详细讲解一下解决 Dev-C++ 运行窗口中文乱码的实现步骤,包括以下内容: 问题描述 在使用 Dev-C++ 进行编程时,如果需要输出中文信息,很可能会出现中文字符乱码的问题,这是因为 Dev-C++ 默认情况下使用的是 ASCII 字符集,而中文字符集是 GBK 或者 UTF-8,需要进行转换才能正确显示。 实现步骤 1. 更改 Dev-…

    人工智能概览 2023年5月25日
    00
  • fastdfs+nginx集群搭建的实现

    以下是“fastdfs+nginx集群搭建的实现”的完整攻略: 准备工作 安装 fastdfs 基础环境 安装 libfastcommon 安装 FastDFS 安装 nginx 和 fastdfs-nginx-module 配置 fastdfs 组件 修改 tracker 的配置文件 tracker.conf。 bash # 修改 tracker_serv…

    人工智能概览 2023年5月25日
    00
  • PHP轻量级数据库操作类Medoo增加、删除、修改、查询例子

    首先,我们需要明确Medoo是一种轻量级的PHP数据库操作类库,其使用方便,可以很好地进行数据库增、删、改、查等操作。 安装Medoo Medoo可以通过Composer来安装。首先在项目中安装Composer,然后在命令行窗口中运行以下代码: composer require catfan/medoo 安装完成后,我们可以在项目中引入Medoo: use …

    人工智能概论 2023年5月24日
    00
  • 华硕灵耀Pro16 2022值得入手吗 华硕灵耀Pro16 2022深度评测

    华硕灵耀Pro16深度评测 华硕灵耀Pro16是一款全新推出的高性能笔记本电脑,是华硕灵耀系列产品的升级版。那么,这款电脑值得入手吗?下面将从外观、配置、性能、续航、价格等多个方面进行分析。 外观设计 华硕灵耀Pro16采用了几何切割风格,通体采用金属材质,并多次经过喷砂、磨砂等多道工艺加工,透出档次感。配备了16.0英寸的全高清屏幕,可以完美的呈现高清画面…

    人工智能概览 2023年5月25日
    00
  • ubuntu16.04自动设置行号的步骤详解

    请注意查看下面的标准markdown格式文本。 Ubuntu16.04自动设置行号的步骤详解 为了提高Linux系统的编程效率,我们有时候需要在vim等编辑器中开启行号功能,方便我们进行代码编写,并且在调试过程中更便捷地排查错误。在下面的几步中,我将详细介绍如何在Ubuntu16.04中自动设置行号功能。 步骤一:检查vim是否已安装 在终端中输入以下命令来…

    人工智能概览 2023年5月25日
    00
  • 巧妙使用python opencv库玩转视频帧率

    下面是“巧妙使用Python OpenCV库玩转视频帧率”的完整攻略。 1. 相关背景知识 在进行本篇攻略之前,您需要先了解以下基本概念: 帧率(Frames Per Second,FPS):视频以每秒多少帧的速度播放,即每秒显示多少张图像。 OpenCV (Open Source Computer Vision Library):是一个计算机视觉的开源库,…

    人工智能概览 2023年5月25日
    00
  • 新手必备Python开发环境搭建教程

    新手必备Python开发环境搭建教程 简介 Python是一门非常流行的编程语言,在多数领域都有广泛的应用。Python的优势在于语法简洁明了,易于学习,同时也有非常强大的开源社区支持。在开始Python编程之前,需要先搭建Python的开发环境。本文将介绍如何在Windows和macOS系统中搭建Python开发环境。 Windows系统 下载Python…

    人工智能概览 2023年5月25日
    00
  • python神经网络Pytorch中Tensorboard函数使用

    介绍 Tensorboard 是一个非常好用的可视化工具,可以方便的帮助我们分析模型训练的表现,并方便我们进一步调优模型。在 PyTorch 中,使用 tensorboardX 库可以将 PyTorch 中的各种操作和训练结果写入 TensorBoard 使用的文件格式,从而实现了与 TensorBoard 的交互。 安装 TensorboardX 在使用 …

    人工智能概论 2023年5月25日
    00
合作推广
合作推广
分享本页
返回顶部