Python量化交易進階講堂-爬蟲抓取東方財富網股吧帖子

歡迎你們訂閱《Python實戰-構建基於股票的量化交易系統》小冊子,小冊子會陸續推出與小冊內容相關的專欄文章,對涉及到的知識點進行更全面的擴展介紹,而且會有選擇地收錄至小冊中,更便於廣大讀者查閱知識點。本篇專欄爲小冊子內容的加推篇!!!html

前言

量化交易策略的研究主要涵蓋了微觀和宏觀這兩個方面,微觀方面更多地是從市場價格和成交持倉這些基礎信息爲研究對象,經過算法計算出技術指標,再從技術指標的變化上構建交易模型。宏觀方面則是基於更多的市場資訊開發交易模型,好比從CPI、PPI、貨幣發行量這些宏觀經濟指標爲研究對象構建交易模型;或者是利用數據挖掘技術重新聞事件中挖掘出可能形成市場異常波動的事件,從而得到交易的時機。正則表達式

咱們知道知名股票論壇有點金投資家園、股天下、東方財富網股吧、和訊股吧、創幻論壇、MACD股市等等,筆者用的比較多的是東方財富網股吧。在小冊子中咱們以爬取東方財富網行業板塊當日的行情數據爲案例,介紹了網絡爬蟲的原理和方法,本節咱們再介紹下如何爬取東方財富網股吧帖子的內容。算法

解析股吧帖子URL

首先經過瀏覽器訪問偉星新材的股吧,查看該網頁的URL爲:http://guba.eastmoney.com/list,002372.html,網頁內容以下圖所示:瀏覽器

當咱們點擊第2頁、第3頁後,查看下當前的URL分別爲:http://guba.eastmoney.com/list,002372_2.htmlhttp://guba.eastmoney.com/list,002372_3.html,所以獲得了個股股吧URL的規律爲http://guba.eastmoney.com/list, 002372_%d.html形式表示,其中的規律比較直白,%d爲論壇第幾頁,不過這個形式是按評論時間排列的網址,若是按發帖時間的排列網址是http://guba.eastmoney.com/list,002372,f_%d.htmlbash

股吧的帖子由兩部分組成,一部分爲「財經評論」或「東方財富網」發佈的公告或官方消息,另外一部分爲散戶發佈的討論帖子,以下圖所示:微信

前者的帖子URL爲http://guba.eastmoney.com/news,cjpl,902659513.html,後者的帖子URL爲http://guba.eastmoney.com/news,002372,902629178.html,二者的URL均可在當前該股股吧HTML文件內容中搜尋到,以下所示:markdown

所以「財經評論」、「東方財富網」或者散戶發佈的帖子,主要的特徵爲/news,在實現上咱們能夠先爬取到股吧HTML內容,而後經過正則表達式來篩選獲得帖子的URL。網絡

關於讀取網頁HTML內容的關鍵代碼咱們已經在小冊子《爬蟲方式獲取行業板塊數據》一節中具體介紹過。須要注意的是Python2的urllib、urllib2和urlparse,已經在Python3中所有被整合到了urllib中,其中Python2的urllib和urllib2中的內容整合爲urllib.request模塊,urlparse整合爲urllib.parse模塊。 獲取到HTML代碼部份內容以下:函數

正則表達式篩選帖子URL,採用了re.compile和re.findall,實現代碼以下,post

pattern = re.compile('/news\S+html',re.S)
news_comment_urls = re.findall(pattern, html_cont.decode('utf-8')) # 非空白字符N次

""" ['/news,cjpl,902659513.html', '/news,cjpl,902684967.html', '/news,cjpl,902602349.html', '/news,cjpl,902529812.html', '/news,cjpl,857016161.html', '/news,002372,902629178.html', '/news,002372,902557935.html', '/news,002372,902533930.html', '/news,002372,902519348.html', '/news,002372,902468635.html', '/news,002372,902466626.html', '/news,002372,902464127.html', ...... '/news,002372,901168702.html', '/news,002372,901153848.html'] """
複製代碼

其中正則表達式的\S+表示匹配屢次非空白字符,而後使用findall函數找到匹配的全部字符串,並把它們做爲一個列表返回。

而後是使用urljoin方法把整個url拼接好用於爬取單個帖子的標題內容,關鍵代碼以下所示:

for comment_url in news_comment_urls :
     whole_url = parse.urljoin(page_url, comment_url)
     post_urls.add(whole_url)
return post_urls
複製代碼

建立爬蟲URL隊列

接下來咱們把全部須要爬取的股吧頁以及每頁中的帖子的URL以隊列的方式進行管理。Python中存儲序列的類型有list、tuple、dict和set,它們之間的區別和特色簡單的說:tuple不能修改其中的元素;set是無序集合,會自動去除重複元素;list是有序的集合;dict是一組key和value的組合。這次咱們選擇list做爲隊列的存儲類型。

建立target_url_manager類,該類包含如下幾個方法:

  • add_page_urls:解析股吧單頁的HTML代碼,得到該頁的帖子URL

  • add_pages_urls:構建隊列,講所有頁的帖子URL創建爲二維list格式

  • has_page_url:判斷隊列是否爲空

  • get_new_url:每次推出一頁的帖子URL

建立隊列形式以下所示:

""" [['http://guba.eastmoney.com/news,002372,899860502.html', 'http://guba.eastmoney.com/news,002372,899832598.html', ...... 'http://guba.eastmoney.com/news,002372,899947046.html', 'http://guba.eastmoney.com/news,002372,899897958.html'], ['http://guba.eastmoney.com/news,cjpl,903685653.html', 'http://guba.eastmoney.com/news,cjpl,903679057.html', ...... 'http://guba.eastmoney.com/news,002372,901739862.html', 'http://guba.eastmoney.com/news,002372,901727241.html']] ['http://guba.eastmoney.com/news,cjpl,903685653.html', 'http://guba.eastmoney.com/news,cjpl,903679057.html', ...... 'http://guba.eastmoney.com/news,002372,901739862.html', 'http://guba.eastmoney.com/news,002372,901727241.html'] """
複製代碼

完整代碼可見小冊子《加推篇!爬蟲抓取東方財富網股吧帖子》。

解析股吧帖子內容

單個帖子爬取的內容包括三部分,帖子發表時間、做者及帖子標題,以下所示:

咱們能夠經過正則表達式進行提取,其中在組合正則表達式時,須要考慮到HTML代碼中是否有重複的匹配關鍵字。做者和帖子標題正則代碼以下,mainbody、zwcontentmain這些關鍵字在文本中僅出現一次,匹配程度較高。因爲網站HTML代碼的改動,表達式須要常常調整。

關鍵代碼以下所示:

com_cont = re.compile(r'<div id="mainbody">.*?zwconttbn.*?<a.*?<font>(.*?)</font>.*?<div.*?class="zwcontentmain.*?">.*?"zwconttbt">(.*?)</div>.*?social clearfix',re.DOTALL)
複製代碼

發佈時間正則代碼以下,分兩步逐漸明晰的去提取時間,因爲search是掃描字符串找到這個 RE 匹配的位置,所以增長group()返回匹配字符串。

pub_elems = re.search('<div class="zwfbtime">.*?</div>',html_cont2).group()
#<div class="zwfbtime">發表於 2020-02-11 09:54:48 東方財富Android版</div>
pub_time = re.search('\d\d\d\d-\d\d-\d\d',pub_elems).group()
#2020-02-06
複製代碼

另外,論壇帖子與當前的股價走勢有時間聯繫,太早的帖子對如今無參考做用,所以須要刪選近期的帖子。咱們能夠對時間進行判斷,只有一個月以內發佈的帖子才進行爬取並存儲。獲取今天的日期使用datetime.now().date(),而後與爬取的帖子時間日期比較,timedelta可在日期上作天days時間計算,但須要將時間轉換爲時間形式。

實現部分關鍵代碼以下所示:

time_start=datetime.now().date() # 獲取日期信息
dt = datetime.strptime(pub_time,"%Y-%m-%d") # 字符串轉時間格式
datetime.date(dt)+timedelta(days=30)
複製代碼

完成了單個帖子的內容爬取以後,咱們採用迭代方法把所有帖子爬取一遍。咱們經過兩層迭代方法,第一層爲頁數,第二層爲一頁的股吧帖子數,將每一個帖子的URL存儲在列表中,經過迭代的方式一個個爬取帖子的內容。

實現部分關鍵代碼以下:

while self.target_page.has_page_url():
     new_urls = self.target_page.get_new_url() # 獲取每一個帖子的URL地址隊列
     for url in new_urls:
		……
複製代碼

當咱們爬取時發現某個帖子不存在,出現爬取信息異常時,可以使用try...except...進行異常處理。

最終爬取到的帖子內容以下圖所示:

完整代碼可見小冊子《加推篇!爬蟲抓取東方財富網股吧帖子》。

帖子內容存儲爲txt

咱們能夠將爬取信息寫到txt文件中,打開方式的代碼實現以下所示,a+爲在文本尾部追加寫入,而不是覆蓋寫入,codecs.open這個方法能夠指定編碼打開文件,而使用Python內置的open打開文件只能寫入str類型。

f=codecs.open(name,'a+','utf-8')
複製代碼

此處咱們建立一個output_txt類,該類中咱們會分別實現打開文件、寫文件和關閉文件這幾個方法。代碼以下所示:

class output_txt(object):

    def open_txt(self):
        name = "stock_cont.txt"
        try:
            f = codecs.open(name, 'a+', 'utf-8')
        except Exception as e:
            print("NO TXT")
        return f

    def out_txt(self, f_handle, conts):
        try:
            print("cont",conts)
            f_handle.write(conts)
        except Exception as e:
            print("NO FILE")

    def close_txt(self, f_handle):
        f_handle.close()
複製代碼

接下來就能夠一邊爬取帖子內容,一邊把內容寫入到txt文件中。實現關鍵代碼以下所示:

file_txt = self.outputer.open_txt()
while self.target_page.has_page_url():
     new_urls = self.target_page.get_new_url() # 獲取每一個帖子的URL地址隊列
     for url in new_urls:
        if time_start <= (self.downloader.find_time(url)+timedelta(days=30)):
           self.outputer.out_txt(file_txt, self.downloader.download(url))
           true_time = true_time + 1
        else:
           error_time = error_time + 1
self.outputer.close_txt(file_txt)
複製代碼

寫入txt文件的效果以下所示:

總結

本小節咱們經過爬蟲方式獲得股吧帖子中的各類內容,那麼這些內容對於咱們來講有什麼意義嗎?咱們發現總有些人一直在唱空,製造恐慌的情緒,不過咱們能夠經過分類分析下這些空頭評論和股價的漲跌有沒有什麼關聯,是否是有寫ID是專門來唱空的呢?感興趣的朋友們能夠試試!

更多的量化交易內容歡迎你們訂閱小冊閱讀!!同時也歡迎你們關注個人微信公衆號【元宵大師帶你用Python量化交易】瞭解更多Python量化交易相關內容

相關文章
相關標籤/搜索