当前位置 : 主页 > 编程语言 > python >

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

来源:互联网 收集:自由互联 发布时间:2023-07-29
Scrapy实现微信公众号文章爬取和分析 微信是近年来备受欢迎的社交媒体应用,在其中运营的公众号也扮演着非常重要的角色。众所周知,微信公众号是一个信息和知识的海洋,因为其中

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

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

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

  1. 安装Scrapy并创建项目

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

pip install scrapy
pip install pymongo
pip 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 scrapy
import re

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()}
登录后复制

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 pymongo

class 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 pd
from pymongo import MongoClient

client = 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 强大的数据分析功能将每个公众号的文章数量进行了可视化展示。

上一篇:如何使用Python正则表达式进行并发操作
下一篇:没有了
网友评论