PHP前端开发

Scrapy实现微信公众号文章爬取和分析

百变鹏仔 1个月前 (01-21) #Python
文章标签 公众

scrapy实现微信公众号文章爬取和分析

微信是近年来备受欢迎的社交媒体应用,在其中运营的公众号也扮演着非常重要的角色。众所周知,微信公众号是一个信息和知识的海洋,因为其中每个公众号都可以发布文章、图文消息等信息。这些信息可以被广泛地应用在很多领域中,比如媒体报道、学术研究等。

那么,本篇文章将介绍如何使用Scrapy框架来实现微信公众号文章的爬取和分析。Scrapy是一个Python的网络爬虫框架,其主要功能是进行数据挖掘和信息查找。因此,Scrapy具有很好的可定制性和高效性。

  1. 安装Scrapy并创建项目

要使用Scrapy框架进行爬虫,首先需要安装Scrapy和其他依赖项。可以使用pip命令进行安装,安装过程如下所示:

pip install scrapypip install pymongopip install mysql-connector-python

安装Scrapy之后,我们需要使用Scrapy命令行工具来创建项目。命令如下:

scrapy startproject wechat

执行该命令后,Scrapy将会创建一个名为“wechat”的项目,并在项目目录中创建许多文件和目录。

  1. 实现微信公众号文章的爬取

在我们开始爬虫之前,我们需要先搞懂微信公众号文章页面的URL格式。一个典型的微信公众号文章页面的URL长这样:

https://mp.weixin.qq.com/s?__biz=XXX&mid=XXX&idx=1&sn=XXX&chksm=XXX#wechat_redirect

其中,__biz 表示微信公众号的ID,mid 表示文章的ID,idx 表示文章的序号,sn 表示文章的签名,chksm 表示内容校验。因此,如果我们要爬取某个公众号的所有文章,就需要找到这个公众号的ID,并用它来构建URL。其中,biz_id 是该公众号的唯一标识。

首先,我们需要准备一个包含许多公众号ID的列表,因为我们要爬取这些公众号的文章。而ID的搜集可以通过各种手段来实现。在这里,我们使用一个包含几个测试ID的列表作为例子:

biz_ids = ['MzU5MjcwMzA4MA==', 'MzI4MzMwNDgwMQ==', 'MzAxMTcyMzg2MA==']

接着,我们需要编写一个Spider,来爬取某个公众号的所有文章。这里,我们将公众号的名字和ID传递到Spider,以方便我们可以处理不同的公众号ID。

import scrapyimport reclass WeChatSpider(scrapy.Spider):    name = "wechat"    allowed_domains = ["mp.weixin.qq.com"]        def __init__(self, name=None, biz_id=None):        super().__init__(name=name)        self.start_urls = ['https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz={}==#wechat_redirect'.format(biz_id)]    def parse(self, response):        article_urls = response.xpath('//h4[1]/a/@href')        for url in article_urls.extract():            yield scrapy.Request(url, callback=self.parse_article)                next_page = response.xpath('//a[@id="js_next"]/@href')        if next_page:            yield scrapy.Request(response.urljoin(next_page[0].extract()), callback=self.parse)        def parse_article(self, response):        url = response.url        title = response.xpath('//h2[@class="rich_media_title"]/text()')        yield {'url': url, 'title': title.extract_first().strip()}

Spider的主要功能是使用给定的公众号ID来访问公众号首页,然后递归地遍历每一页,提取所有文章的URL。此外,parse_article方法用于提取文章的URL和标题,以进行后续处理。总体而言,该Spider不是很复杂,但是提取速度较慢。

最后,我们需要在Terminal中输入下面的命令来启动Spider:

scrapy crawl wechat -a biz_id=XXXXXXXX

同样,我们也可以爬取多个公众号,只需要在命令中指定所有公众号的ID即可:

scrapy crawl wechat -a biz_id=ID1,ID2,ID3
  1. 存储文章数据

爬取文章之后,我们需要将文章的标题和URL保存到数据库(如MongoDB、MySQL等)。在这里,我们将使用pymongo库来保存爬取到的数据。

import pymongoclass MongoPipeline(object):    collection_name = 'wechat'    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_DATABASE', 'items')        )    def open_spider(self, spider):        self.client = pymongo.MongoClient(self.mongo_uri)        self.db = self.client[self.mongo_db]    def close_spider(self, spider):        self.client.close()    def process_item(self, item, spider):        self.db[self.collection_name].insert_one(dict(item))        return item

在该Pipeline中,我们使用了MongoDB作为存储数据的后端。可以根据需要修改这个类来使用其他的数据库系统。

接下来,我们需要在settings.py文件中配置数据库相关的参数:

MONGO_URI = 'mongodb://localhost:27017/'MONGO_DATABASE = 'wechat'ITEM_PIPELINES = {'myproject.pipelines.MongoPipeline': 300}

最后,我们在Spider中调用Pipeline,以将数据存储到MongoDB中:

class WeChatSpider(scrapy.Spider):    name = "wechat"    allowed_domains = ["mp.weixin.qq.com"]        def __init__(self, name=None, biz_id=None):        super().__init__(name=name)        self.start_urls = ['https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz={}==#wechat_redirect'.format(biz_id)]    def parse(self, response):        article_urls = response.xpath('//h4[1]/a/@href')        for url in article_urls.extract():            yield scrapy.Request(url, callback=self.parse_article)                next_page = response.xpath('//a[@id="js_next"]/@href')        if next_page:            yield scrapy.Request(response.urljoin(next_page[0].extract()), callback=self.parse)                def parse_article(self, response):        url = response.url        title = response.xpath('//h2[@class="rich_media_title"]/text()')        yield {'url': url, 'title': title.extract_first().strip()}        pipeline = response.meta.get('pipeline')        if pipeline:            item = dict()            item['url'] = url            item['title'] = title.extract_first().strip()            yield item

在上面的代码中,response.meta.get('pipeline')是用来获取我们在Spider中设置的Pipeline的对象的。因此,只需在Spider代码中添加如下代码,就可以支持Pipeline了:

yield scrapy.Request(url, callback=self.parse_article, meta={'pipeline': 1})
  1. 数据分析

最后,我们将使用Scrapy和pandas等库来实现数据的分析和可视化。

在这里,我们将从MongoDB中提取我们爬取到的数据,并将其保存到CSV文件中。随后,我们可以使用pandas来对CSV文件进行处理,并进行可视化。

以下是实现过程:

import pandas as pdfrom pymongo import MongoClientclient = MongoClient('mongodb://localhost:27017/')db = client['wechat']articles = db['wechat']cursor = articles.find()doc = list(cursor)df = pd.DataFrame(doc)df.to_csv('wechat.csv', encoding='utf-8')df.groupby('biz_id')['title'].count().plot(kind='bar')

以上代码中,我们使用了 MongoDB 和 Pandas 库来将爬取到的数据保存到 CSV 文件的 data 文件夹内。随后,我们使用 Pandas 强大的数据分析功能将每个公众号的文章数量进行了可视化展示。