記python3爬取東方財(cái)富股吧滬深帖子及用戶信息

記python3爬取東方財(cái)富股吧滬深帖子及用戶信息

一. 簡(jiǎn)介

爬蟲并沒有使用流行的框架,原因是以前并沒有接觸過爬蟲 想通過自己慢慢實(shí)現(xiàn)來找找感覺。

程序使用了多進(jìn)程+多線程统抬,實(shí)現(xiàn)了首次全部爬取和增量爬取引颈。

按我的理解蛉抓,爬蟲主要要干的就是:

  • 下載網(wǎng)頁
  • 解析網(wǎng)頁
  • 存儲(chǔ)內(nèi)容

下載請(qǐng)求使用的是requests伺糠,解析和獲取內(nèi)容使用的是lxml檀轨、xpath和re胸竞。

存儲(chǔ)方面我則是用了mongodb,這也是我第一次使用NoSQL参萄。其實(shí)使用mongodb部分原因是想用用非關(guān)系數(shù)據(jù)庫卫枝,借機(jī)了解學(xué)習(xí)= =。還有使用了redis作為消息隊(duì)列讹挎。

二. 數(shù)據(jù)庫存儲(chǔ)

使用非關(guān)系數(shù)據(jù)庫的話校赤,就要學(xué)會(huì)摒棄關(guān)系型數(shù)據(jù)庫的思維吆玖,反范式化。

不得不說马篮,開頭的時(shí)候我還是傻傻地把表按關(guān)系型的思維去設(shè)計(jì)了沾乘。

東方財(cái)富股吧數(shù)據(jù)表字段

User集合

字段名 類型 描述
_id ObjectId ObjectID
id string 網(wǎng)站用戶id
url string 用戶主頁鏈接
nickname string 用戶昵稱
avator string 用戶頭像鏈接
reg_date ISODate 注冊(cè)日期
following_count int 關(guān)注數(shù)
fans_count int 粉絲數(shù)
influence int 影響力
introduce string 用戶簡(jiǎn)介
visit_count int 總訪問數(shù)
post_count int 發(fā)帖數(shù)
comment_count int 評(píng)論數(shù)
optional_count int 自選數(shù)
capacity_circle List(存放code) 能力圈
source string 所屬論壇

Post 集合

字段名 類型 描述
_id ObjectId Objectid
id string 帖子id
url string 帖子鏈接
user_nickname string 作者昵稱
title string 帖子標(biāo)題
created_at ISODate 發(fā)表時(shí)間
content string 帖子內(nèi)容(見下)
type string 帖子類型
code string 所屬板塊代碼
comment_count int 評(píng)論數(shù)
comments List 評(píng)論列表,里面存放comment文檔(見下)
last_update_at ISODate 最后更新時(shí)間
like_count int 點(diǎn)贊數(shù)
page_count int 帖子頁數(shù)
source string 來源(eastmoney)
type string 帖子類型(有hinfo浑测、normal還有qa)
user_id string 作者id
user_influence string 作者影響力
user_age string 作者吧齡
view_count int 瀏覽量

文章與評(píng)論采用內(nèi)嵌形式

采用內(nèi)嵌而不是引用的理由:

  • 場(chǎng)景是使用爬蟲爬取文本內(nèi)容做分析而不是作為論壇數(shù)據(jù)庫使用翅阵,多數(shù)帖子評(píng)論較少,最多的大概是幾千條迁央,基本不會(huì)超過16MB的限制掷匠。
  • 且未來文本分析主要操作是讀取,讀取內(nèi)容為主帖+每條評(píng)論岖圈,使用內(nèi)嵌形式的話進(jìn)行一次查詢即可讹语。
  • 缺點(diǎn)是占用更多空間。

Comment 評(píng)論文檔

字段名 類型 描述
id string 評(píng)論id(唯一)
user_nickname string 評(píng)論用戶昵稱
user_id String 評(píng)論用戶id
created_at ISODate 發(fā)表時(shí)間
content string 評(píng)論內(nèi)容
like_count int 點(diǎn)贊數(shù)
user_influence int 評(píng)論用戶影響力
user_age String 評(píng)論用戶吧齡
reply_to document 回復(fù)的評(píng)論的內(nèi)容(見下表)

reply_to 文檔

字段名 類型 描述
reply_to_user_nickname string 回復(fù)的評(píng)論的用戶昵稱
reply_to_comment string 回復(fù)的評(píng)論的內(nèi)容
reply_to_comment_id string 回復(fù)的評(píng)論的id

當(dāng)帖子類型為qa(問董秘)時(shí)蜂科,帖子的內(nèi)容形式有變化顽决。此時(shí)帖子的content則存放question和answer,其中question為string导匣,而answer為文檔集侯,如下速妖。

answer 文檔

字段名 類型 描述
content string 答復(fù)內(nèi)容
from string 答復(fù)來自
time ISODate 答復(fù)時(shí)間

實(shí)例如下:

{
    "_id" : ObjectId("5af30cc7e99de146ba385258"),
    "url" : "http://guba.eastmoney.com/news,600000,758450707.html",
    "code" : "600000",
    "comment_count" : "1",
    "comments" : [ 
        {
            "id" : "8692649074",
            "user_nickname" : "很S很天真",
            "user_id" : "6303084653682694",
            "created_at" : ISODate("2018-05-07T18:51:56.000Z"),
            "content" : "浦發(fā)的每一次反彈都是撤離的好機(jī)會(huì)冀墨!",
            "reply_to" : "",
            "like_count" : 0,
            "user_influence" : 5,
            "user_age" : "1.9年"
        }
    ],
    "content" : {
        "question" : "為何2017年的現(xiàn)金分紅對(duì)比2016年大幅縮減钥屈?導(dǎo)致5月2號(hào)股票價(jià)格大跌。",
        "answer" : {
            "from" : "上證e互動(dòng)",
            "time" : "2018-05-07 17:32:47",
            "content" : "公司2017年度利潤(rùn)分配預(yù)案主要基于:一是在國家持續(xù)推進(jìn)供給側(cè)改革和去杠桿過程中厕氨,銀行業(yè)風(fēng)險(xiǎn)管控壓力持續(xù)上升进每,對(duì)銀行抗風(fēng)險(xiǎn)能力提出更高的要求;二是2018年為資本達(dá)標(biāo)過渡期最后一年命斧,對(duì)商業(yè)銀行資本充足水平提出了更高要求田晚;三是隨著公司集團(tuán)化、國際化戰(zhàn)略的不斷推進(jìn)国葬,集團(tuán)及各子公司健康快速發(fā)展贤徒,對(duì)于資本補(bǔ)充的需求也顯著上升;四是公司加快結(jié)構(gòu)轉(zhuǎn)型汇四,注重科技引領(lǐng)接奈,加快建設(shè)數(shù)字生態(tài)銀行,科研投入占比有所增加通孽,需要充足的資本支撐序宦。公司綜合考慮監(jiān)管機(jī)構(gòu)的相關(guān)要求、自身盈利水平和資本充足狀況背苦、以及轉(zhuǎn)型發(fā)展的需要互捌,適當(dāng)提高了利潤(rùn)留存比例以補(bǔ)充資本潘明,提升公司防范金融風(fēng)險(xiǎn)、服務(wù)實(shí)體經(jīng)濟(jì)秕噪、深化金融改革的能力钳降。感謝您的關(guān)注!"
        }
    },
    "created_at" : ISODate("2018-05-03T11:15:25.000Z"),
    "id" : "758450707",
    "last_update_at" : ISODate("2018-05-07T18:51:56.000Z"),
    "like_count" : 0,
    "page_count" : 1,
    "source" : "eastmoney",
    "title" : "為何2017年的現(xiàn)金分紅對(duì)比2016年大",
    "type" : "qa",
    "uesr_nickname" : "順民izeoyl",
    "user_age" : "2.8年",
    "user_id" : "4661094379663388",
    "user_influence" : 0,
    "view_count" : "2642"
}

三.爬取過程

爬取的思路大概是這樣的:

1.首先要獲取到所有的股票代碼

東方財(cái)富個(gè)股吧里有所有的股票信息腌巾,我只選取了滬A和深A(yù)的股票作為爬取對(duì)象遂填。

所以的話,第一步就是就將這些股票代碼爬取下來澈蝙,保存到redis中城菊。

2.能夠獲取一個(gè)股票代碼版塊的所有帖子鏈接

可以選擇頁數(shù)較少的股票先作為目標(biāo),比如 浙江美大002677 這只股票碉克,其版塊鏈接為http://guba.eastmoney.com/list,002677.html

大概有167頁,每頁最多有80個(gè)帖子并齐。要能夠把這么多個(gè)帖子鏈接記錄下來漏麦,然后后面再挨個(gè)爬取里面的詳細(xì)內(nèi)容。

3.能夠獲取一個(gè)帖子里面的所有內(nèi)容

每獲取完一個(gè)帖子里的所有內(nèi)容况褪,就把它保存到數(shù)據(jù)庫中撕贞。

在這個(gè)過程中,把所有發(fā)帖留言的用戶id都記錄下來测垛。

4.能夠獲取用戶的信息

爬取前先判斷用戶id是否已經(jīng)保存在redis的set中捏膨。若不存在,則獲取用戶信息食侮,然后保存到數(shù)據(jù)庫号涯,并且把用戶id插入到redis的set中(set能夠自動(dòng)去重)。


這四步都完成后锯七,爬蟲就完成啦链快。

第二步就可以使用多進(jìn)程去操作,每個(gè)進(jìn)程從redis里取一個(gè)任務(wù)眉尸,然后執(zhí)行第三步域蜗。

而第三、四步則可以用多線程噪猾,因?yàn)檫@兩步屬于IO密集型的任務(wù)霉祸。

四. 細(xì)節(jié)

我在爬取東方財(cái)富股吧的過程中發(fā)現(xiàn)它好像沒有設(shè)置反爬機(jī)制?對(duì)新手很友好哇袱蜡。但是我們還是秉著原則time.sleep(x)一下丝蹭。


關(guān)于第一步 獲取所有股票代碼

爬蟲的第一步?jīng)]有什么坑,按照靜態(tài)頁面思路爬取即可戒劫,主要是熟悉了xpath的使用半夷。


關(guān)于第二步 獲取某個(gè)版塊的所有帖子

要獲取所有帖子婆廊,第一反應(yīng)就是想到遍歷每一頁,那得先知道版塊頁數(shù)對(duì)吧巫橄?然后發(fā)現(xiàn)版塊下面就有了淘邻,如下圖。

屏幕快照 2018-05-11 下午5.45.31.png

但是發(fā)現(xiàn)這個(gè)是屬于動(dòng)態(tài)內(nèi)容湘换,所以我是用到了selenium無頭模式獲取這個(gè)版塊的頁數(shù)宾舅,比如浙江美大版塊 共 167 頁。其中彩倚,在服務(wù)器中如果要用selenium得要用庫pyvirtualdisplay筹我。然后在使用selenium的地方加上

display = Display(visible=0, size=(800, 800))   

display.start() 

獲取到頁面數(shù)之后,就開始用for循環(huán)獲取每一頁內(nèi)容帆离,把頁面上基本的信息保存下來蔬蕊。

尤其是帖子的鏈接,在第三步獲取帖子里面的內(nèi)容哥谷,就得請(qǐng)求帖子鏈接岸夯。

頁數(shù)范圍 = 用selenium獲取的頁數(shù)
for i in 頁數(shù)范圍:
    獲取(http://guba.eastmoney.com/list,002677_i.html)的帖子信息

其實(shí)后面我想到?jīng)]必要用selenium獲取這個(gè)頁數(shù)们妥,直接在while循環(huán)內(nèi)讓頁數(shù)遞增猜扮,當(dāng)獲取不到頁面元素時(shí)直接捕捉異常退出while循環(huán)就可以了吧= =。

這步遇到的坑就是监婶,當(dāng)爬取內(nèi)容前旅赢,得先了解要爬取的目標(biāo)!惑惶!

比如帖子原來有公告煮盼,比賽問董秘集惋,研報(bào)孕似,新聞普通帖子多種形式。

所以要分析這些帖子里面的內(nèi)容形式是不是相同的9涡獭喉祭!否則解析部分就會(huì)不對(duì)= =。比如一開始我看了幾頁數(shù)據(jù)雷绢,都沒注意到有問董秘這種東西泛烙。。翘紊。


關(guān)于第三步 獲取帖子詳細(xì)內(nèi)容

帖子的標(biāo)題蔽氨,內(nèi)容還有評(píng)論內(nèi)容都是靜態(tài)內(nèi)容,可以很容易獲取到的。

但是作者鹉究、評(píng)論用戶的吧齡及影響力宇立,還有帖子及評(píng)論的點(diǎn)贊數(shù)則都是要用ajax獲取到的。

用chrome打開控制臺(tái)Network得到這些鏈接自赔。如下圖所示妈嘹,以下得到的是每個(gè)用戶的id、吧齡和影響力绍妨。

屏幕快照 2018-05-11 下午6.08.01.png

請(qǐng)求鏈接Requests URL如下圖所示润脸,可以看到關(guān)鍵就是要構(gòu)造action=xx后面的id和replyids

屏幕快照 2018-05-11 下午6.10.14.png

所以的話他去,每次想要獲取帖子里所有用戶的吧齡和影響力毙驯,就是先獲取到他們的用戶id,以及評(píng)論id灾测,構(gòu)造出類似上面的鏈接獲取信息爆价。

構(gòu)造形式大概就是/../guba.aspx?action=getreplylikegd&id=xxx&replyids=xxx%7Cxxx%2Cxxx%7Cxxx….

7C后面接的是評(píng)論的id,2C后面接的是評(píng)論用戶的id媳搪。即對(duì)于評(píng)論允坚,是要有這條評(píng)論本身的id以及評(píng)論用戶的id一起才行的。

屏幕快照 2018-05-11 下午6.14.11.png

返回結(jié)果為如上蛾号,把最外層的括號(hào)去掉,然后用json庫解析數(shù)據(jù)獲取里面的內(nèi)容即可涯雅。

再后面就遇到坑了O式帷!;钅妗:

有的帖子有很多的評(píng)論用戶精刷,構(gòu)造出來的鏈接就會(huì)包括很多用戶和評(píng)論id。此時(shí)就可能超過了一定的上限蔗候,比如幾百條回復(fù)怒允,你構(gòu)造了超級(jí)長(zhǎng)的鏈接請(qǐng)求,結(jié)果可能只返回了前30條锈遥。纫事。。(具體多少我沒去留意)

所以所灸,我就分開多次獲取丽惶,每次獲取30條再保存起來。

其它的部分也類似上述過程啦爬立。


最最后

程序可以跑啦钾唬!

結(jié)果,卻發(fā)現(xiàn)還是會(huì)有報(bào)錯(cuò)。抡秆。奕巍。(痛苦)

后面嘗試輸出錯(cuò)誤頁面鏈接,發(fā)現(xiàn)了東財(cái)很多奇怪的地方儒士。的止。。

比如坑1:

屏幕快照 2018-04-28 下午6.18.13.png
屏幕快照 2018-04-28 下午6.18.22.png

中科信息吧的帖子打開竟然是中科曙光的UЧ稹冲杀?= =

坑2:

屏幕快照 2018-05-09 下午9.12.29.png

有的帖子出現(xiàn)在了版塊中,打開卻會(huì)是不存在睹酌。

坑3:

屏幕快照 2018-05-10 下午9.34.14.png

這雖然是問董秘類型的帖子权谁,但其實(shí)應(yīng)該是公告類型的。憋沿。旺芽。(仔細(xì)看,會(huì)發(fā)現(xiàn)和上面兩條的公告是一樣的)

進(jìn)去里面并沒有問答的內(nèi)容辐啄,所以解析頁面的時(shí)候就會(huì)報(bào)錯(cuò)采章!

坑4:

屏幕快照 2018-05-09 下午9.28.48.png

好吧,原來還有“上海手機(jī)網(wǎng)友”這種玩意壶辜。悯舟。。
你沒法獲取到它的用戶id(壓根沒有)和昵稱(內(nèi)容不再是在a標(biāo)簽里砸民,而是在span標(biāo)簽里)抵怎。評(píng)論里也一樣會(huì)出現(xiàn)“上海手機(jī)網(wǎng)友”。岭参。反惕。

針對(duì)上述情況,修改下代碼即可演侯。

ok姿染,單進(jìn)程單線程能正常跑了,加上多線程和多進(jìn)程提高爬蟲速度秒际。

五.增量爬取

首次爬取完全部的內(nèi)容了悬赏,假設(shè)后面想獲取更新內(nèi)容呢?立馬想到的是根據(jù)時(shí)間來判斷娄徊。

版塊中帖子的最后更新時(shí)間數(shù)據(jù)庫中該板塊的最新時(shí)間作比較舷嗡,如果發(fā)現(xiàn)頁面中的時(shí)間比數(shù)據(jù)庫里的新,就把帖子爬下來嵌莉。

結(jié)果還是遇到坑了进萄,首先,東財(cái)版塊頁面每條帖子后面顯示的最后更新時(shí)間是不包含年份的,這樣的話可能遇到某些特殊情況會(huì)出問題中鼠?于是可婶,我就嘗試獲取帖子的最新評(píng)論的發(fā)表時(shí)間,這個(gè)時(shí)間是包含年月日的援雇。

請(qǐng)求鏈接為:http://guba.eastmoney.com/news,xxxxxx,xxxxxxxx,d.html#storeply

請(qǐng)求帶d的帖子鏈接矛渴,第一條評(píng)論就是最新評(píng)論。


本以為這就可以了惫搏,實(shí)際運(yùn)行發(fā)現(xiàn)爬沒幾條就停止了具温。發(fā)現(xiàn)這些帖子都有一個(gè)問題,就是它們在版塊中顯示的最后更新時(shí)間最新一條評(píng)論的發(fā)表時(shí)間并不相同筐赔!

后面細(xì)心點(diǎn)才發(fā)現(xiàn)問題所在

版塊頁面每條帖子后面顯示的最后更新時(shí)間并不一定代表帖子有新評(píng)論铣猩,也可能是帖子中有點(diǎn)贊行為(猜測(cè)是吧,實(shí)際中我嘗試回帖茴丰、點(diǎn)贊达皿,帖子都不是立即被置頂?shù)?/strong>)。

而當(dāng)時(shí)保存在數(shù)據(jù)庫中的最后更新時(shí)間 其實(shí)是 主帖中最后一條評(píng)論的發(fā)表時(shí)間贿肩,這個(gè)不一定和版塊頁面中顯示的最后更新時(shí)間是相同的峦椰。

所以就出現(xiàn)了這樣的情況:有的帖子沒有新評(píng)論,但是有點(diǎn)贊行為汰规,帖子被頂上去了汤功,然而程序如果看到這樣的帖子,就以為爬完了(因?yàn)榘鎵K頁面的時(shí)間是最新的溜哮,但最后一條評(píng)論的發(fā)表時(shí)間和數(shù)據(jù)庫中的最后更新時(shí)間相同)冤竹。

后面想了一個(gè)解決方法是:設(shè)定一個(gè)上限N,只有連續(xù)獲取的N條帖子情況都這樣(連續(xù)N條帖子都是由純點(diǎn)贊行為導(dǎo)致的可能性是很小的吧)才認(rèn)為把最新的內(nèi)容都爬取完茬射。

這么弄了后,觀察下來增量爬取好像沒什么問題了冒签。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末在抛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子萧恕,更是在濱河造成了極大的恐慌刚梭,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件票唆,死亡現(xiàn)場(chǎng)離奇詭異朴读,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)走趋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門衅金,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事氮唯〖担” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵惩琉,是天一觀的道長(zhǎng)豆励。 經(jīng)常有香客問我,道長(zhǎng)瞒渠,這世上最難降的妖魔是什么良蒸? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮伍玖,結(jié)果婚禮上嫩痰,老公的妹妹穿的比我還像新娘。我一直安慰自己私沮,他們只是感情好始赎,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著仔燕,像睡著了一般造垛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晰搀,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天五辽,我揣著相機(jī)與錄音,去河邊找鬼外恕。 笑死杆逗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鳞疲。 我是一名探鬼主播罪郊,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼尚洽!你這毒婦竟也來了悔橄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤腺毫,失蹤者是張志新(化名)和其女友劉穎癣疟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潮酒,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡睛挚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了急黎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扎狱。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡侧到,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出委乌,到底是詐尸還是另有隱情床牧,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布遭贸,位于F島的核電站戈咳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏壕吹。R本人自食惡果不足惜著蛙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望耳贬。 院中可真熱鬧踏堡,春花似錦、人聲如沸咒劲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腐魂。三九已至帐偎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蛔屹,已是汗流浹背削樊。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兔毒,地道東北人漫贞。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像育叁,于是被迫代替她去往敵國和親迅脐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

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