Scrapy實現微信公眾號文章爬取和分析
微信是近年來備受歡迎的社群媒體應用,在其中運作的公眾號也扮演著非常重要的角色。眾所周知,微信公眾號是一個資訊和知識的海洋,因為其中每個公眾號都可以發布文章、圖文訊息等資訊。這些資訊可以被廣泛地應用在許多領域中,例如媒體報道、學術研究等。
那麼,這篇文章將介紹如何使用Scrapy框架來實現微信公眾號文章的爬取與分析。 Scrapy是一個Python的網路爬蟲框架,主要功能是進行資料探勘和資訊查找。因此,Scrapy具有很好的可自訂性和高效性。
要使用Scrapy框架進行爬蟲,首先需要安裝Scrapy和其他相依性。可以使用pip指令進行安裝,安裝過程如下所示:
pip install scrapy pip install pymongo pip install mysql-connector-python
安裝Scrapy之後,我們需要使用Scrapy命令列工具來建立專案。指令如下:
scrapy startproject wechat
執行指令後,Scrapy將會建立一個名為「wechat」的項目,並在專案目錄中建立許多檔案和目錄。
在我們開始爬蟲之前,我們需要先搞懂微信公眾號文章頁的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
爬取文章之後,我們需要將文章的標題和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})
最後,我們將使用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 強大的數據分析功能將每個公眾號的文章數量進行了視覺化展示。
以上是Scrapy實現微信公眾號文章爬取與分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!