Python爬蟲實戰系列文章目錄
Python爬蟲實戰:東方财富網股吧資料爬取(一)
Python爬蟲實戰:東方财富網股吧資料爬取(二)
Python爬蟲實戰:東方财富網股吧資料爬取(三)
Python爬蟲實戰:東方财富網股吧資料爬取(四)
目錄
- Python爬蟲實戰系列文章目錄
- 前言
- 一、項目說明
- 二、實施過程
-
- 1.明确擷取網頁中哪些資料
- 2.檢視網頁源代碼分析結構
-
- ① 網頁源代碼
- ② 網頁連結
- 3.爬蟲需要具備的功能
- 4.爬取結果
- 總結
- 寫在最後
前言
朋友托我寫個爬蟲,本身是個爬蟲小白的我還是接受了此次重任,總共曆時五天左右,過程中遇到過無數bug,好在一路披荊斬棘,還是大差不差的完成了此次委托!但感覺這次的經曆還是有必要和大家分享一下,正好最近也沒有寫博文了,趁這次機會趕趕進度!
一、項目說明
項目需求:股吧中人們的言論行為和股市漲跌的延遲相關性
資料來源:東方财富網、熱門個股吧
資料字段:閱讀、評論、标題、作者、更新時間
實作功能:讀取每個公司股吧的全部頁面的資料并寫入excel表中
二、實施過程
以東方财富吧為例
1.明确擷取網頁中哪些資料
我們需要爬取的是東方财富吧中全部發帖資訊的閱讀、評論、标題、作者及最後更新時間這五個字段的資料,我一開始想也不是很難,解析一下網頁比對一下對應的标簽值就可以了,但後面還是出現了各種各樣的問題,需要大家注意一下。
2.檢視網頁源代碼分析結構
① 網頁源代碼
首先打開網頁的開發者工具(Ctrl+Shift+i),在源代碼中查找對應字段的标簽結構。
從圖中可以看出,這五個字段分别位于
<span></span>
行标簽内,對應的屬性分别是
"l1 a1"、"l2 a2"、"l3 a3"、"l4 a4"、"l5 a5"
。想必大家已經有思路了,我們可以通過先擷取網頁代碼,再解析網頁查詢對應的五個字段,最後做一個提取就可以了。
② 網頁連結
【東方财富吧:300059】
首頁:https://guba.eastmoney.com/list,300059.html
第二頁:https://guba.eastmoney.com/list,300059_2.html
可以看出個股吧連結主要由三部分組成:list、名稱代碼、頁數
I.全部個股吧的數字代碼
II. 翻頁資料
如何得到不同股吧的所有翻頁資料,着實讓我找了好久,各種資源我都找了可惜還是沒有發現,突然無意之中我找到了解決辦法,我直接一個好家夥!
跟上述的五類字段一樣,我們檢視一下頁數的代碼字段,如下圖所示:
我的第一個辦法是直接解析網頁後找到
<span></span>
标簽下的
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.爬蟲需要具備的功能
基本問題解決了,我們可以開始編寫爬蟲了。這部分不講代碼原理,隻解釋代碼功能。自己也是小白,如果代碼存在問題或不清楚的話,歡迎大家在下方留言,我一定及時回複。
① 擷取網頁源代碼
def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
print("擷取網頁内容失敗!")
② 解析網頁并提取資料字段
def parsePage(html):
list = [] # 我用的二維數組存儲
read = []
comment = []
title = []
author = []
time = []
try:
# print(html)
soup = BeautifulSoup(html, "html.parser")
for each in soup.find_all('span', 'l1 a1'):
if '萬' in each.string:
each.string = each.string[:-2]
read.append(each.string)
read = read[1:] # read[0] == '閱讀'
list.append(read)
for each in soup.find_all('span', 'l2 a2'):
comment.append(each.string)
comment = comment[1:] # comment[0] == '評論'
list.append(comment)
for each in soup.find_all('span', 'l3 a3'):
first = each.select('a:nth-of-type(1)')
for i in first:
i.find_all("a")
# print(i.title)
title.append(i.title)
list.append(title)
for each in soup.find_all('span', 'l4 a4'):
first = each.select('font:nth-of-type(1)')
for i in first:
i.find_all("font")
# print(i.title)
author.append(i.title)
list.append(author)
for each in soup.find_all('span', 'l5 a5'):
time.append(each.string)
time = time[1:] # time[0] == '最後更新'
list.append(time)
except:
print("解析網頁字段失敗!")
return list
③ 擷取貼吧總頁數
基于解析的網頁直接find_all也是可以的
def get_total_pages_num(url):
try:
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument(')
chrome_options.add_argument(
'User-Agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/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)
if page_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()
except Exception as e:
total_pages = 1
return int(total_pages)
4.爬取結果
上述代碼基本的字段已經可以實作爬取了,結果如下:
可以看到,我這裡的時間多了年份,這是由于朋友研究的需要,在基于一次爬取的結果上,進行二次爬取标題所帶的連結網頁獲得的,有關二次爬取的内容,我們再下一節再和大家分享。
總結
在爬取過程中,我還遇到了很多問題諸如:
① 部分文章結構不同或存在備援該如何處理(問董秘等連結)
② 爬取過程中ip被屏蔽自動跳轉頁面該如何處理(代理IP池)
… …
這些内容在後續章節中再和大家分享,下期再見啦!
寫在最後
【學習交流】
WX:WL1498544910
【文末小宣傳】
----部落客自己開發的小程式,希望大家的點贊支援一下,謝謝!-----