當前位置:首頁 > 科技 > 正文

Python爬蟲實戰:東方财富網股吧數據爬取(一)

Python爬蟲實戰系列文章目錄




目錄


前言

朋友托我寫個爬蟲,本身是個爬蟲小白的我還是接受了此次重任,總共曆時五天左右,過程中遇到過無數bug,好在一路披荊斬棘,還是大差不差的完成了此次委托!但感覺這次的經曆還是有必要和大家分享一下,正好最近也沒有寫博文了,趁這次機會趕趕進度!

一、項目說明

項目需求:股吧中人們的言論行為和股市漲跌的延遲相關性
數據來源:、
數據字段:閱讀、評論、标題、作者、更新時間
實現功能:讀取每個公司股吧的全部頁面的數據并寫入excel表中

二、實施過程

以為例

1.明确獲取網頁中哪些數據

我們需要爬取的是東方财富吧中全部發帖信息的閱讀評論标題作者最後更新時間這五個字段的數據,我一開始想也不是很難,解析一下網頁匹配一下對應的标簽值就可以了,但後面還是出現了各種各樣的問題,需要大家注意一下。


2.查看網頁源代碼分析結構

① 網頁源代碼

首先打開網頁的開發者工具(Ctrl+Shift+i),在源代碼中查找對應字段的标簽結構。


從圖中可以看出,這五個字段分别位于行标簽内,對應的屬性分别是"l1 a1"、"l2 a2"、"l3 a3"、"l4 a4"、"l5 a5"。想必大家已經有思路了,我們可以通過先獲取網頁代碼,再解析網頁查詢對應的五個字段,最後做一個提取就可以了。

② 網頁鍊接

【東方财富吧:300059】
首頁:
第二頁:
可以看出個股吧鍊接主要由三部分組成:list、名稱代碼、頁數

I.的數字代碼


II. 翻頁數據

如何得到不同股吧的所有翻頁數據,着實讓我找了好久,各種資源我都找了可惜還是沒有發現,突然無意之中我找到了解決辦法,我直接一個好家夥!

跟上述的五類字段一樣,我們查看一下頁數的代碼字段,如下圖所示:


我的第一個辦法是直接解析網頁後找到标簽下的sumpage屬性,其内容即為總頁數,本來以為原來這麼好獲取,結果解析完才發現,pagernums裡的内容是動态的,即span.on是會随頁而變化的,故直接requests并不能獲取到,但是還是被我發現了玄機!


大家可以看data-pager這裡,裡面的内容是list,300059_|452885|80|2,我對比了幾個頁面後發現其中數字分别代表的是:

300059:股吧數字代碼452885:該股吧共發帖452885條
80:每個頁面分别有80條貼子
2:當前所處頁面為第2頁

那麼這時候,我們就可以直接用累積多年的算力(小學除法)算出東方财富吧共有452885/80=5661.0625,向上取整共5662頁!如果你也脫口而出好家夥的話,請在屏幕下方打出來!


3.爬蟲需要具備的功能

基本問題解決了,我們可以開始編寫爬蟲了。這部分不講代碼原理,隻解釋代碼功能。自己也是小白,如果代碼存在問題或不清楚的話,歡迎大家在下方留言,我一定及時回複。

① 獲取網頁源代碼

defgetHTMLText(url):try:r=requests.get(url,timeout=30)r.raise_for_status()r.encoding=r.apparent_encodingreturnr.textexcept:print("獲取網頁内容失敗!")

② 解析網頁并提取數據字段

defparsePage(html):list=[]#我用的二維數組存儲read=[]comment=[]title=[]author=[]time=[]try:#print(html)soup=BeautifulSoup(html,"html.parser")foreachinsoup.find_all('span','l1a1'):if'萬'ineach.string:each.string=each.string[:-2]read.append(each.string)read=read[1:]#read[0]=='閱讀'list.append(read)foreachinsoup.find_all('span','l2a2'):comment.append(each.string)comment=comment[1:]#comment[0]=='評論'list.append(comment)foreachinsoup.find_all('span','l3a3'):first=each.select('a:nth-of-type(1)')foriinfirst:i.find_all("a")#print(i.title)title.append(i.title)list.append(title)foreachinsoup.find_all('span','l4a4'):first=each.select('font:nth-of-type(1)')foriinfirst:i.find_all("font")#print(i.title)author.append(i.title)list.append(author)foreachinsoup.find_all('span','l5a5'):time.append(each.string)time=time[1:]#time[0]=='最後更新'list.append(time)except:print("解析網頁字段失敗!")returnlist

③ 獲取貼吧總頁數

基于解析的網頁直接find_all也是可以的
defget_total_pages_num(url):try:chrome_options=webdriver.ChromeOptions()chrome_options.add_argument('--headless')chrome_options.add_argument('lang=zh_CN.UTF-8')chrome_options.add_argument('User-Agent="Mozilla/5.0(Macintosh;IntelMacOSX10_12_6)AppleWebKit/537.36(KHTML,likeGecko)Chrome/65.0.3325.162Safari/537.36"')chrome_options.add_argument('--disable-extensions')chrome_options.add_argument('--disable-gpu')chrome_options.add_argument('--no-sandbox')driver=webdriver.Chrome(options=chrome_options)driver.get(url)page_data=driver.find_element_by_xpath('//div[@id="mainbody"]/div[@id="articlelistnew"]/div[@class="pager"]/span[@class="pagernums"]').get_attribute('data-pager')#print(page_data)ifpage_data:#page_nums=re.findall('\|(\d+)',page_data[0])page_nums=page_data.split("|")#print(page_nums)total_pages=math.ceil(int(page_nums[1])/int(page_nums[2]))driver.quit()exceptExceptionase:total_pages=1returnint(total_pages)

4.爬取結果

上述代碼基本的字段已經可以實現爬取了,結果如下:


可以看到,我這裡的時間多了年份,這是由于朋友研究的需要,在基于一次爬取的結果上,進行二次爬取标題所帶的鍊接網頁獲得的,有關二次爬取的内容,我們再下一節再和大家分享。


總結

在爬取過程中,我還遇到了很多問題諸如:
① 部分帖子結構不同或存在冗餘該如何處理(問董秘等鍊接)
② 爬取過程中ip被屏蔽自動跳轉頁面該如何處理(代理IP池)
… …
這些内容在後續章節中再和大家分享,下期再見啦!

你可能想看:

有話要說...

取消
掃碼支持 支付碼