爬取朋友圈杏节,Get年度關(guān)鍵詞

人生苦短,我用Python && C#典阵。

朋友圈年度關(guān)鍵詞

1.引言

最近初學(xué)Python奋渔,寫爬蟲上癮。爬了豆瓣練手壮啊,又爬了公司的論壇生成詞云分析年度關(guān)鍵詞嫉鲸。最近琢磨著2017又僅剩兩月了,我的年度關(guān)鍵詞是啥歹啼?
所以自然想到爬取下自己的微信朋友圈玄渗,來(lái)個(gè)詞頻分析座菠,生成屬于自己的年度關(guān)鍵詞詞云。

朋友圈的爬取是非常有難度的藤树,因?yàn)槲⑿鸥緵](méi)有暴露API入口去爬取數(shù)據(jù)浴滴。
但它山之石,可以攻玉也榄。
通過(guò)各種搜索發(fā)現(xiàn)巡莹,已經(jīng)有第三方工具可以做到朋友圈的導(dǎo)出司志。其中微信公眾號(hào)【出書啦】就提供了這樣一種服務(wù)甜紫,支持朋友圈導(dǎo)出,并排版生成微信書骂远。

而對(duì)朋友圈的爬取就是基于【出書啦】爬取朋友圈后生成網(wǎng)頁(yè)后的二次爬取囚霸。
有點(diǎn)爬蟲經(jīng)驗(yàn)的,只要拿到導(dǎo)出朋友圈的URL激才,后面的爬蟲就不足為道了拓型。但本著分享和總結(jié)的精神,還是和大家娓娓道來(lái)瘸恼。

=文中涉及個(gè)人隱私內(nèi)容做了特殊處理=

2.獲取朋友圈數(shù)據(jù)入口

上面已經(jīng)介紹過(guò)了朋友圈的數(shù)據(jù)爬取是基于【出書啦】微信公眾號(hào)生成的在線微信書數(shù)據(jù)的二次爬取劣挫。

具體步驟很簡(jiǎn)單:

  1. 關(guān)注【出書啦】微信公眾號(hào)
  2. 點(diǎn)擊【創(chuàng)作書籍】-->【微信書】-->【開始制作】-->【添加隨機(jī)分配的出書啦小編為好友即可】
  3. 稍等片刻,微信書制作完畢东帅,會(huì)收到小編發(fā)送的消息提醒压固,如下圖所示。
小編發(fā)送的制作結(jié)果

點(diǎn)擊上圖的鏈接靠闭,我們就可以看到按照月份重新排版的朋友圈數(shù)據(jù)帐我,如下圖所示:


重新排版后的微信朋友圈數(shù)據(jù)

至此,我們拿到朋友圈的數(shù)據(jù)入口——【出書啦】排版生成的微信書鏈接愧膀。

寫過(guò)爬蟲的拦键,后面就可以直接略過(guò)了。
當(dāng)然檩淋,沒(méi)寫過(guò)爬蟲也不想動(dòng)手的芬为,也可以把【出書啦】生成的微信書鏈接留言或私信給我,我?guī)湍惬@取年度關(guān)鍵詞蟀悦。

3.環(huán)境準(zhǔn)備

本文所寫爬蟲基于python2.7 + scrapy + jieba + wordcloud媚朦,使用VS Code IDE。

  1. Scrapy為Python中比較流行的爬蟲框架熬芜。
  2. Jieba是比較好用的中文分詞模塊莲镣。
  3. Wordcloud 用于生成詞云。

4.生成爬蟲項(xiàng)目

第一步:命令行執(zhí)行scrapy startproject weixin_moment涎拉,生成Scrapy爬蟲項(xiàng)目瑞侮。
第二步:進(jìn)入創(chuàng)建的weixin_moment目錄的圆,執(zhí)行scrapy genspider 'moment' 'chushu.la'創(chuàng)建朋友圈爬蟲。
執(zhí)行以上兩步后的文件夾結(jié)構(gòu)如下:

爬蟲項(xiàng)目結(jié)構(gòu)

5.分析數(shù)據(jù)源

數(shù)據(jù)的準(zhǔn)確抓取半火,需要對(duì)數(shù)據(jù)源進(jìn)行準(zhǔn)確分析越妈。這一步我們就要來(lái)分析【出書啦】生成的微信書鏈接的數(shù)據(jù)加載方式。老規(guī)矩钮糖,F(xiàn)12開發(fā)者工具用起來(lái)梅掠。

Http請(qǐng)求之目錄

從上圖我們可以看出這是一個(gè)get請(qǐng)求,返回的json類型格式數(shù)據(jù)店归。

點(diǎn)擊Preview頁(yè)簽可以看到如下圖所示的數(shù)據(jù):

返回的目錄結(jié)果

從圖中可以看到返回的目錄導(dǎo)航數(shù)據(jù)包阎抒,其數(shù)據(jù)是按月份進(jìn)行加載的。當(dāng)點(diǎn)擊導(dǎo)航按鈕消痛,其加載對(duì)應(yīng)月份的朋友圈數(shù)據(jù)且叁。

導(dǎo)航

我們點(diǎn)擊【2014-3】再觀察網(wǎng)絡(luò)請(qǐng)求,發(fā)現(xiàn)如下請(qǐng)求:

導(dǎo)航分頁(yè)請(qǐng)求

從以上數(shù)據(jù)我們可以明細(xì)看出秩伞,其采用的是用json傳參的post的方式請(qǐng)求數(shù)據(jù)包逞带。點(diǎn)擊Preview頁(yè)簽,看到返回的分頁(yè)JSON數(shù)據(jù)包纱新。

分頁(yè)請(qǐng)求返回的數(shù)據(jù)包

展開某個(gè)節(jié)點(diǎn)展氓,我們可以發(fā)現(xiàn)朋友圈數(shù)據(jù)藏在data/paras節(jié)點(diǎn)下。

朋友圈數(shù)據(jù)

至此脸爱,我們完成數(shù)據(jù)的來(lái)源分析遇汞。

6.蜘蛛來(lái)也

完成了數(shù)據(jù)源分析,我們只需構(gòu)造數(shù)據(jù)請(qǐng)求阅羹,并進(jìn)行正確的數(shù)據(jù)解析勺疼,即可拿到我們想要的數(shù)據(jù)!

6.1.請(qǐng)求導(dǎo)航數(shù)據(jù)包

修改moment.py定義start_requests方法:

bookid = '12345678'  #請(qǐng)?zhí)顚憽境鰰病糠祷劓溄又械臄?shù)字部分
def start_requests(self):
        """
        使用get方式請(qǐng)求導(dǎo)航數(shù)據(jù)包
        """
        url = 'http://chushu.la/api/book/chushula-{0}?isAjax=1'.format(self.bookid)  #獲取目錄的url
        yield scrapy.Request(url, callback=self.parse)

重載parse方法捏鱼,解析獲取到的導(dǎo)航數(shù)據(jù)包:

def parse(self, response):
        """
        處理獲取到的導(dǎo)航數(shù)據(jù)包
        """
        json_body = json.loads(response.body)  #加載json數(shù)據(jù)包
        catalogs = json_body['book']['catalogs']  #獲取json中的目錄數(shù)據(jù)包

6.2. 發(fā)送導(dǎo)航請(qǐng)求执庐,抓取朋友圈數(shù)據(jù)

根據(jù)上面跟蹤到發(fā)出的http導(dǎo)航請(qǐng)求,要想抓取到朋友圈數(shù)據(jù)导梆,我們需要根據(jù)發(fā)出的請(qǐng)求參數(shù)構(gòu)造參數(shù)轨淌。



從上圖可知,主要包含五個(gè)參數(shù):

  1. type:"year_month"為默認(rèn)值
  2. year: 年份
  3. month: 月份
  4. index: 第幾頁(yè)
  5. value : 由年月拼接的字符串

繼續(xù)修改我們的parse方法看尼,遍歷我們第一步抓取到的導(dǎo)航數(shù)據(jù)包構(gòu)造請(qǐng)求參數(shù):

def parse(self, response):
        """
        處理獲取到的導(dǎo)航數(shù)據(jù)包
        """
        json_body = json.loads(response.body)  #加載json數(shù)據(jù)包
        catalogs = json_body['book']['catalogs']  #獲取json中的目錄數(shù)據(jù)包
        url = 'http://chushu.la/api/book/wx/chushula-{0}/pages?isAjax=1'.format(self.bookid) #分頁(yè)數(shù)據(jù)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

因?yàn)閺奈覀兏櫟降膆ttp請(qǐng)求來(lái)看是基于json傳參的post請(qǐng)求:
所以我們要這樣發(fā)起請(qǐng)求:

yield scrapy.Request(
                url,
                method='POST',
                body=json.dumps(formdata),
                headers={'Content-Type': 'application/json'},
                callback=self.parse_moment)

同樣我們需要定義一個(gè)回調(diào)函數(shù)用來(lái)處理返回的朋友圈數(shù)據(jù)递鹉。定義parse_moment方法,根據(jù)返回的json數(shù)據(jù)包進(jìn)行數(shù)據(jù)提炔卣丁:

def parse_moment(self, response):
        """
        朋友圈數(shù)據(jù)處理
        """
        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"):# 僅抓取朋友圈分頁(yè)數(shù)據(jù)
                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']#獲取時(shí)間
                    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()  #朋友圈文字

至此我們完成爬蟲的書寫狰域。是不是迫不及待跑一下媳拴。

6.3. 蜘蛛爬起來(lái)

命令行執(zhí)行scrapy crawl moment -o moment.json黄橘,稍等片刻,熱乎的朋友圈數(shù)據(jù)就生成到moment.json文件中了屈溉。

爬取到的朋友圈文本

7. 分詞處理

jieba中文分詞提供了便利的接口用于分詞和詞頻統(tǒng)計(jì)塞关。我們直接調(diào)用jieba.cut方法即可得到分詞結(jié)果。在此之前我們需要加載我們爬取的朋友圈數(shù)據(jù)子巾,即保存到moment.json文件中的數(shù)據(jù)帆赢,并拼接所有朋友圈文本傳參至jieba.cut即可。
新添加一個(gè)analyse.py文件线梗,定義analyse_words方法:

# -*- coding: utf-8 -*-

"""分析導(dǎo)出的朋友圈數(shù)據(jù)"""

import json
import os

import jieba
from wordcloud import WordCloud


def analyse_words():
    """
    分析抓取到的朋友圈數(shù)據(jù)椰于,使用jieba進(jìn)行分詞,使用wordcloud生成詞云
    """
    curr_path = os.path.dirname(__file__)  # 當(dāng)前文件文件夾所在目錄
    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]  # 獲取朋友圈文字?jǐn)?shù)組
        contents = ' '.join(moments)  # 拼接為長(zhǎng)文本
        cut_texts = ' '.join(jieba.cut(contents))  # 使用結(jié)巴分詞進(jìn)行中文分詞

8. 生成關(guān)鍵詞詞云

詞云需要基于上一步的分詞結(jié)果生成詞云缠导。代碼也很簡(jiǎn)單:

cloud = WordCloud(font_path=font_path)
        wordcloud = cloud.generate(cut_texts)  #生成詞云
        wordcloud.to_file('keys.png')  #保存圖片
        image = wordcloud.to_image()  # 轉(zhuǎn)化為圖片
        image.show()  # 展示圖片

最后在文件末尾調(diào)用analyse_words()廉羔,命令行執(zhí)行python analyse.py即可生成關(guān)鍵詞溉痢!

生成的詞云

你可能嫌棄以上生成的詞云比較丑僻造,沒(méi)關(guān)系,你可以使用wordart做出各種酷炫的效果孩饼。

9. 最后

因?yàn)椤境鰰病课赐晟品磁罊C(jī)制髓削,所以爬蟲寫下來(lái)也沒(méi)有什么難度,所以感興趣的不妨趕緊動(dòng)手試一試镀娶。本文出于學(xué)習(xí)分享立膛,無(wú)惡意竊取數(shù)據(jù)之意,也請(qǐng)讀者不要用于他途梯码!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末宝泵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子轩娶,更是在濱河造成了極大的恐慌儿奶,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳄抒,死亡現(xiàn)場(chǎng)離奇詭異闯捎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)许溅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門瓤鼻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人贤重,你說(shuō)我怎么就攤上這事茬祷。” “怎么了并蝗?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵祭犯,是天一觀的道長(zhǎng)耐朴。 經(jīng)常有香客問(wèn)我,道長(zhǎng)盹憎,這世上最難降的妖魔是什么筛峭? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮陪每,結(jié)果婚禮上影晓,老公的妹妹穿的比我還像新娘。我一直安慰自己檩禾,他們只是感情好挂签,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盼产,像睡著了一般饵婆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上戏售,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天侨核,我揣著相機(jī)與錄音,去河邊找鬼灌灾。 笑死搓译,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锋喜。 我是一名探鬼主播些己,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼嘿般!你這毒婦竟也來(lái)了段标?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤炉奴,失蹤者是張志新(化名)和其女友劉穎逼庞,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盆佣,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡往堡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了共耍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虑灰。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖痹兜,靈堂內(nèi)的尸體忽然破棺而出穆咐,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布对湃,位于F島的核電站崖叫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拍柒。R本人自食惡果不足惜心傀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拆讯。 院中可真熱鬧脂男,春花似錦、人聲如沸种呐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)爽室。三九已至汁讼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阔墩,已是汗流浹背嘿架。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留戈擒,地道東北人眶明。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像筐高,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子丑瞧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容