人生苦短,我用Python && C#。python
最近初學Python,寫爬蟲上癮。爬了豆瓣練手,又爬了公司的論壇生成詞雲分析年度關鍵詞。最近琢磨着2017又僅剩兩月了,個人年度關鍵詞是啥?
因此天然想到爬取下本身的微信朋友圈,來個詞頻分析,生成屬於本身的年度關鍵詞詞雲。git
朋友圈的爬取是很是有難度的,由於微信根本沒有暴露API入口去爬取數據。
但它山之石,能夠攻玉。
經過各類搜索發現,已經有第三方工具能夠作到朋友圈的導出。其中微信公衆號【出書啦】就提供了這樣一種服務,支持朋友圈導出,並排版生成微信書。github
而對朋友圈的爬取就是基於【出書啦】爬取朋友圈後生成網頁後的二次爬取。
有點爬蟲經驗的,只要拿到導出朋友圈的URL,後面的爬蟲就不足爲道了。但本着分享和總結的精神,仍是和你們娓娓道來。json
=文中涉及我的隱私內容作了特殊處理=api
上面已經介紹過了朋友圈的數據爬取是基於【出書啦】微信公衆號生成的在線微信書數據的二次爬取。數組
具體步驟很簡單:微信
點擊上圖的連接,咱們就能夠看到按照月份從新排版的朋友圈數據,以下圖所示:
網絡
至此,咱們拿到朋友圈的數據入口——【出書啦】排版生成的微信書連接。app
寫過爬蟲的,後面就能夠直接略過了。
固然,沒寫過爬蟲也不想動手的,也能夠把【出書啦】生成的微信書連接留言或私信給我,我幫你獲取年度關鍵詞。框架
本文所寫爬蟲基於python2.7 + scrapy + jieba + wordcloud,使用VS Code IDE。
第一步:命令行執行scrapy startproject weixin_moment
,生成Scrapy爬蟲項目。
第二步:進入建立的weixin_moment目錄,執行scrapy genspider 'moment' 'chushu.la'
建立朋友圈爬蟲。
執行以上兩步後的文件夾結構以下:
數據的準確抓取,須要對數據源進行準確分析。這一步咱們就要來分析【出書啦】生成的微信書連接的數據加載方式。老規矩,F12開發者工具用起來。
從上圖咱們能夠看出這是一個get請求,返回的json類型格式數據。
點擊Preview頁籤能夠看到以下圖所示的數據:
從圖中能夠看到返回的目錄導航數據包,其數據是按月份進行加載的。當點擊導航按鈕,其加載對應月份的朋友圈數據。
咱們點擊【2014-3】再觀察網絡請求,發現以下請求:
從以上數據咱們能夠明細看出,其採用的是用json傳參的post的方式請求數據包。點擊Preview頁籤,看到返回的分頁JSON數據包。
展開某個節點,咱們能夠發現朋友圈數據藏在data/paras節點下。
至此,咱們完成數據的來源分析。
完成了數據源分析,咱們只需構造數據請求,並進行正確的數據解析,便可拿到咱們想要的數據!
修改moment.py定義start_requests
方法:
bookid = '12345678' #請填寫【出書啦】返回連接中的數字部分 def start_requests(self): """ 使用get方式請求導航數據包 """ url = 'http://chushu.la/api/book/chushula-{0}?isAjax=1'.format(self.bookid) #獲取目錄的url yield scrapy.Request(url, callback=self.parse)
重載parse
方法,解析獲取到的導航數據包:
def parse(self, response): """ 處理獲取到的導航數據包 """ json_body = json.loads(response.body) #加載json數據包 catalogs = json_body['book']['catalogs'] #獲取json中的目錄數據包
根據上面跟蹤到發出的http導航請求,要想抓取到朋友圈數據,咱們須要根據發出的請求參數構造參數。
從上圖可知,主要包含五個參數:
繼續修改咱們的parse
方法,遍歷咱們第一步抓取到的導航數據包構造請求參數:
def parse(self, response): """ 處理獲取到的導航數據包 """ json_body = json.loads(response.body) #加載json數據包 catalogs = json_body['book']['catalogs'] #獲取json中的目錄數據包 url = 'http://chushu.la/api/book/wx/chushula-{0}/pages?isAjax=1'.format(self.bookid) #分頁數據url start_page = int(catalogs[0]['month']) #獲取起始月份做爲index傳值 for catalog in catalogs: year = catalog['year'] month = catalog['month'] formdata = { "type": 'year_month', "year": year, "month": month, "index": str(start_page), "value": 'v_{0}{1}'.format(year, month) } start_page += 1
由於從咱們跟蹤到的http請求來看是基於json傳參的post請求:
因此咱們要這樣發起請求:
yield scrapy.Request( url, method='POST', body=json.dumps(formdata), headers={'Content-Type': 'application/json'}, callback=self.parse_moment)
一樣咱們須要定義一個回調函數用來處理返回的朋友圈數據。定義parse_moment
方法,根據返回的json數據包進行數據提取:
def parse_moment(self, response): """ 朋友圈數據處理 """ json_body = json.loads(response.body) pages = json_body['pages'] pattern = re.compile(u"[\u4e00-\u9fa5]+") #匹配中文 item = WeixinMomentItem() for page in pages: if (page['type'] == "weixin_moment_page"):# 僅抓取朋友圈分頁數據 paras = page['data']['paras'] if paras: moment = '' for content in paras[0]['rows']: result = re.findall(pattern, content['data']) #使用正則匹配全部中文朋友圈 moment += ''.join(result) item['moment'] = moment item['date'] = page['data']['dateText']#獲取時間 yield item
以上用到了定義的WeixinMomentItem
。修改items.py,作以下修改:
class WeixinMomentItem(scrapy.Item): """ 朋友圈Item """ # define the fields for your item here like: # name = scrapy.Field() date = scrapy.Field() #日期 moment = scrapy.Field() #朋友圈文字
至此咱們完成爬蟲的書寫。是否是火燒眉毛跑一下。
命令行執行scrapy crawl moment -o moment.json
,稍等片刻,熱乎的朋友圈數據就生成到moment.json文件中了。
jieba中文分詞提供了便利的接口用於分詞和詞頻統計。咱們直接調用jieba.cut
方法便可獲得分詞結果。在此以前咱們須要加載咱們爬取的朋友圈數據,即保存到moment.json文件中的數據,並拼接全部朋友圈文本傳參至jieba.cut
便可。
新添加一個analyse.py
文件,定義analyse_words
方法:
# -*- coding: utf-8 -*- """分析導出的朋友圈數據""" import json import os import jieba from wordcloud import WordCloud def analyse_words(): """ 分析抓取到的朋友圈數據,使用jieba進行分詞,使用wordcloud生成詞雲 """ curr_path = os.path.dirname(__file__) # 當前文件文件夾所在目錄 parent_path = os.path.dirname(curr_path) # 上層目錄 file_path = os.path.join(parent_path, 'moment.json') font_path = os.path.join(parent_path, "simhei.ttf") if not os.path.isfile(file_path): return with open(file_path) as moment_file: data = json.load(moment_file) # 使用json加載文件 moments = [item.get('moment', '') for item in data] # 獲取朋友圈文字數組 contents = ' '.join(moments) # 拼接爲長文本 cut_texts = ' '.join(jieba.cut(contents)) # 使用結巴分詞進行中文分詞
詞雲鬚要基於上一步的分詞結果生成詞雲。代碼也很簡單:
cloud = WordCloud(font_path=font_path) wordcloud = cloud.generate(cut_texts) #生成詞雲 wordcloud.to_file('keys.png') #保存圖片 image = wordcloud.to_image() # 轉化爲圖片 image.show() # 展現圖片
最後在文件末尾調用analyse_words()
,命令行執行python analyse.py
便可生成關鍵詞!
你可能嫌棄以上生成的詞雲比較醜,不要緊,你可使用wordart作出各類酷炫的效果。
由於【出書啦】未完善反爬機制,因此爬蟲寫下來也沒有什麼難度,因此感興趣的不妨趕忙動手試一試。本文出於學習分享,無惡意竊取數據之意,也請讀者不要用於他途!