Python從小白到大牛——項目實戰:爬取搜狐證券股票數據

2022-01-09 書圈

『善者,吾善之;不善者,吾亦善之;德善。信者,吾信之;不信者,吾亦信之,德信。』

——《道德經》第四十九章

網際網路是一個巨大的資源庫,只要方法適當,就可以找到你所需要的數據。少量的數據可以人工去找,但是對於大量的數據,而且數據獲取之後還要進行解析,那麼靠人工就無法完成這些任務,因此就需要通過一個電腦程式來完成這些工作,這就是網絡爬蟲。

『提示:Python社區中有一個網絡爬蟲框架——Scrapy(https://scrapy.org/),Scrapy封裝了網絡爬蟲的技術細節,使得開發人員編寫網絡爬蟲更加方便。這裡並不介紹Scrapy框架,而是介紹實現網絡爬蟲的基本技術。通過一個爬取股票數據項目,介紹網絡爬蟲技術。』

下面將介紹一個完整的網絡爬蟲項目,該項目是從搜狐網爬取貴州茅臺股票數據,然後進行解析,解析之後的結果保存到資料庫中,以備以後使用。

掃碼優惠購書



搜狐網數據是動態數據,需要使用Selenium庫爬取數據。相關代碼如下:


"""項目實戰:搜狐網爬取股票數據"""import datetime
from selenium import webdriver
url = 'http://q.stock.sohu.com/cn/600519/lshq.shtml'

def fetch_data(): """爬取並解析數據"""
driver = webdriver.Firefox() driver.get(url)
table_element = driver.find_element_by_id('BIZ_hq_historySearch') tr_list = table_element.find_elements_by_xpath('./tbody/tr') ①
data = [] ②
for idx, tr in enumerate(tr_list): ③ if idx == 0: ④ continue
td_list = tr.find_elements_by_tag_name('td') ⑤ fields = {} ⑥ fields['Date'] = td_list[0].text fields['Open'] = float(td_list[1].text) fields['Close'] = float(td_list[2].text) fields['Low'] = float(td_list[5].text) fields['High'] = float(td_list[6].text) fields['Volume'] = float(td_list[7].text) data.append(fields) ⑦

driver.quit() return data

if __name__ == '__main__': data = fetch_data() print(data)

上述代碼將爬取數據和解析數據封裝在fetch_data()函數中,該函數返回列表數據。代碼第①行是在table_element對象(id為BIZ_hq_historySearch 的table標籤)中通過XPath表達式「./tbody/tr」查找符合條件的所有元素,XPath表達式「./tbody/tr」是查找table中tbody中所有tr標籤,每個tr是table中的一行。查找結果返回tr_list對象,如圖1-1所示tr_list。

代碼第②行定義一個列表對象data,用了保存從table中解析出來的數據。代碼第③行遍歷tr_list列表對象。通過enumerate()函數可以拆分idx和tr變量,idx是循環變量。因為table的第一行是其他數據的匯總,不應該提取這一行數據,代碼第④行當idx == 0是時跳第一行數據。代碼第⑤行tr對象中通過td標籤名查詢所有元素,如圖1-1所示td_list。代碼第⑥行創建字典對象fields ,每一個fields 對象可以保存table中一條tr數據。代碼第⑦行將每一個fields對象放到data列表中。

檢測數據是否更新

由於網絡爬蟲需要定期從網頁上爬取數據,但是如果網頁中的數據沒有更新,本次爬取的數據與上次一樣,就沒有必要進行解析和存儲了。驗證兩次數據是否完全相同可以使用MD5數字加密技術,MD5可以對任意長度的數據進行計算,得到固定長度的MD5碼。MD5的典型應用是對一段數據產生信息摘要,以防止被篡改。通過MD5函數對兩次請求返回的HTML數據進行計算,生成的MD5相同則說明數據沒有更新,否則數據已經更新。

Python中計算MD5碼可以使用hashlib模塊中的md5()函數。實現檢測數據更新的代碼如下:


"""項目實戰:搜狐網爬取股票數據"""import hashlibimport os
from selenium import webdriver
url = 'http://q.stock.sohu.com/cn/600519/lshq.shtml'

def check_update(html): """驗證數據是否更新,更新返回True,未更新返回False"""
md5obj = hashlib.md5() ① md5obj.update(html.encode(encoding='utf-8')) ② md5code = md5obj.hexdigest() ③ print(md5code)
old_md5code = '' f_name = 'md5.txt' ④
if os.path.exists(f_name): with open(f_name, 'r', encoding='utf-8') as f: ⑥ old_md5code = f.read()
if md5code == old_md5code: ⑦ print('數據沒有更新') return False else: with open(f_name, 'w', encoding='utf-8') as f: f.write(md5code) ⑧ print('數據更新') return True

def fetch_data(): """爬取並解析數據"""
driver = webdriver.Firefox() driver.get(url)
table_element = driver.find_element_by_id('BIZ_hq_historySearch') ⑨ if not check_update(table_element.text): driver.quit() return None
… … driver.quit() return data
if __name__ == '__main__': data = fetch_data()

上述代碼第①行~第③行是生成MD5碼的主要語句。首先通過代碼第①行md5()函數創建md5對象。代碼第②行使用update()方法對傳入的數據進行MD5運算,注意update()方法的參數是字節序列對象,而html.encode(encoding='utf-8')是將字符串轉換為字節序列。代碼第③行是請求MD5摘要,hexdigest()方法返回一個十六進位數字所構成的MD5碼。

代碼第④行定義變量f_name,用來保存上次MD5碼的文件名。代碼第⑤行判斷文件是否存在,如果存在則會讀取MD5碼,見代碼第⑥行。代碼第⑦行是比較兩次的MD5碼,如果一致說明沒有更新,返回False;否則返回True,並將新的MD5碼寫入到文件中,見代碼第⑧行。代碼第⑨行是通過查找id為BIZ_hq_historySearch的table元素對象table_element。代碼第⑩行調用check_update()函數驗證股票數據是否更新,其中table_element.text提取table元素中的所有文本。注意如果沒有更新數據時需要則通過driver.quit()語句退出瀏覽器釋放資源。

保存數據到資料庫

數據解析完成後需要保存到資料庫中。該項目的資料庫設計模型如圖1-2所示,項目中包含兩個數據表,股票信息表(Stocks)和股票歷史價格表(HistoricalQuote)。

圖1-2 資料庫設計模型

資料庫設計完成後需要編寫資料庫DDL腳本。當然,也可以通過一些工具生成DDL腳本,然後把這個腳本放在資料庫中執行就可以了。下面是編寫的DDL腳本文件crebas.sql。

create database if not exists QuoteDB;
use QuoteDB;
drop table if exists HistoricalQuote;
drop table if exists Stocks;
create table HistoricalQuote( HDate varchar(10) not null, Open decimal(8,4), High decimal(8,4), Low decimal(8,4), Close decimal(8,4), Volume bigint, Symbol varchar(10), primary key (HDate));

create table Stocks( Symbol varchar(10) not null, Company varchar(50) not null, primary key (Symbol));
alter table HistoricalQuote add constraint FK_Reference_1 foreign key (Symbol) references Stocks (Symbol) on delete restrict on update restrict;

insert into Stocks (Symbol, Company) values ('600519', '貴州茅臺'); ①

在創建完成資料庫後,還在股票信息表中預先插入了一條數據,見代碼第①行。編寫DDL腳本之後需要在MySQL數據中執行,創建資料庫。

資料庫創建完成後,編寫訪問資料庫的Python代碼如下:


import pymysql

def insert_hisq_data(row): """在股票歷史價格表中傳入數據"""
connection = pymysql.connect(host='localhost', user='root', password='12345', database='QuoteDB', charset='utf8') try: with connection.cursor() as cursor:
sql = 'insert into historicalquote ' \ '(HDate,Open,High,Low,Close,Volume,Symbol)' \ ' values (%(Date)s,%(Open)s,%(High)s,%(Low)s,%(Close)s,%(Volume)s,%(Symbol)s)' ①
cursor.execute(sql, row) ②
connection.commit()
except pymysql.DatabaseError as error: connection.rollback() print('插入數據失敗{0}'.format(error)) finally: connection.close()

訪問資料庫代碼是在db_access模塊中編寫的。代碼第①行是插入數據SQL語句,其中(%(Date)s等是命名佔位符,綁定時需要字典類型。代碼第②行是綁定參數並執行SQL語句,其中row是要綁定的參數,row是字典類型。

調用db_access模塊代碼如下:

...
if __name__ == '__main__': data = fetch_data() print(data)
if data is not None: for row in data: ① row['Symbol'] = '600519' ② db_access.insert_hisq_data(row) ③

上述代碼第①行是循環遍歷data變量,data保存了所有爬蟲爬取的數據。代碼第②行添加Symbol到row中,爬取的數據沒有Symbol。代碼第③行是調用db_access模塊的insert_hisq_data()函數插入數據到資料庫。

爬蟲工作計劃任務

網絡中的數據一般都是定期更新的,網絡爬蟲不需要一直工作,可以根據數據更新頻率或更新數據時間點,制訂網絡爬蟲工作計劃任務。例如股票信息在交易日內是定時更新的,股票交易日是周一至周五,當然還有特殊的日期不進行交易,股票交易時間是上午時段9:30~11:30,下午時段13:00~15:00。本項目有些特殊爬取的數據不是實時數據,而是歷史數據,這種歷史數據應該在交易日結束之後爬取。

本項目需要兩個子線程,一個是工作子線程,另一個是控制子線程。具體代碼如下:


"""項目實戰:搜狐網爬取股票數據"""import datetimeimport hashlibimport osimport threadingimport time
import db_accessfrom selenium import webdriver
url = 'http://q.stock.sohu.com/cn/600519/lshq.shtml'
is_running = Trueinterval = 60 * 60

def check_update(html): """驗證數據是否更新,更新返回True,未更新返回False"""
<省略驗證數據是否更新代碼>

def fetch_data(): """爬取並解析數據""" <省略爬取並解析數據代碼>

def is_trad_time(): ① """判斷交易時間"""
now = datetime.datetime.now() df = '%H%M%S' strnow = now.strftime(df) starttime1 = datetime.time(9, 30).strftime(df) endtime1 = datetime.time(11, 30).strftime(df) starttime2 = datetime.time(13, 0).strftime(df) endtime2 = datetime.time(15, 0).strftime(df)
if now.weekday() == 5 \ or now.weekday() == 6 \ or not ((strnow >= starttime1 and strnow <= endtime1) \ or (strnow >= starttime2 and strnow <= endtime2)): return False return True

def work_thread_body(): """工作線程體函數"""
while is_running: print('爬蟲休眠...') time.sleep(interval) if is_trad_time(): print('交易時間,爬蟲不工作...') continue
print('非交易時間,爬蟲開始工作...')
data = fetch_data()
if data is not None: for row in data: row['Symbol'] = '600519' db_access.insert_hisq_data(row)

def main(): """主函數"""
work_thread = threading.Thread(target=work_thread_body, name='WorkThread') work_thread.start()

if __name__ == '__main__': main()

工作線程根據指定計劃任務完成解析數據和數據保存。工作線程啟動後會調用線程體work_thread_body()函數,在線程體函數中代碼第③行讓工作線程休眠。代碼第行調用is_trad_time()函數判斷是否是交易時間,如果是交易時間繼續休眠;如果是非交易時間,爬蟲開始工作。

另外,代碼第①行是判斷交易的時間函數,該函數可以判斷當前時間是否是股票交易時間。代碼第行中now.weekday() == 5是判斷當前日期是星期六,now.weekday() == 6是判斷當前日期是星期日,(strnow >= starttime1 and strnow <= endtime1)是判斷當前時間是在上午時段9:30~11:30,(strnow >= starttime2 and strnow <= endtime2)是判斷當前時間是在下午時段13:00~15:00。

項目編寫完成後就可以進行測試了。圖1-3是項目的控制臺,如果在不在交易時間內,爬蟲開始工作,然後休眠;如果在交易時間內,爬蟲休眠。


相關焦點

  • Python從小白到大牛——項目實戰:貴州茅臺股票數據可視化
    ——《道德經》第五十五章大量的數據中蘊藏著豐富的信息,如果能夠讓這些數據清晰地、友好地、漂亮地展示出來,那麼你就可能會發現這些信息。例如股票的數據量很大,但通過股票的K線圖能夠看出股票的走勢,從而幫助你下決定。Python的數據可視化庫有很多,但是應用有不同的方向。
  • 超適合Python小白的乾貨,Python數據分析50個實戰項目
    2.大話NBA | 用數據帶你回顧喬丹的職業生涯3.分析幾十萬條知乎數據,我挖掘出了這些秘密4.用(大)數據全方位解讀電視劇《大秦帝國之崛起》5.以虎嗅網4W+文章的文本挖掘為例,展現數據分析的一整套流程6.從大數據輿情傳播角度看《三生三世十裡桃花》7.北京二手房房價分析8.kaggle數據分析實踐項目練習
  • 最全從Python小白到大牛,要走的路這裡都有(初級篇)
    從Python小白到大牛,要走的路這裡都有面向項目的學習是學習編碼的最佳方法。Python是當今最需求的語言,為了幫助您學習它,以下是一些您可以探索的最重要的Python項目:Python遊戲Python圖像編程CIFAR10在Python中使用TensorFlow開始看吧,和從開始到放棄說再見俗話說的好,沒吃過豬肉還沒見過豬跑?
  • python爬取數據存入資料庫
    昨天本來寫了一篇關於python爬取的文章,結果沒通過,正好今天一起吧。用python同時實現爬取,和存入資料庫,算是複習一下前面操作資料庫的知識。1、準備工作既然是爬取,那自然要連接到爬取的頁面,所以需要requests庫。
  • 最全從Python小白到大牛,要走的路這裡都有(一)
    從Python小白到大牛,要走的路這裡都有面向項目的學習是學習編碼的最佳方法。Python雖然對大多數小白來說,可能是從入門到放棄的過程。探究起來,可能初入門的同學沒見到過Python美麗的全景,一直埋頭寫hello world太多了,喪失了對Python的愛才是放棄的主要原因吧。在本文中,將用真實的代碼給你展示從小白到大牛Python項目之旅。只要你敢看,我就敢寫。開始吧!
  • 愛數課實驗 | 利用Python爬取股票交易數據
    1 數據源信息介紹1.1 數據來源網站股票市場交易信息在網絡上隨處可查,但有的網站將數據流放在js中,相對來說難以統一處理;有的網站域名結構不夠清晰,無效字符比較多。經過對比,本案例選用股城網來進行股票交易數據的爬取。1.2 選取目標數據在股城網上,有著各種板塊的行情信息,診斷信息,各個股票的行情走勢,基本資料,高管介紹,資金流向等各類信息。
  • python爬蟲實戰:爬取天氣數據的實例詳解
    在本篇文章裡小編給大家整理的是一篇關於python爬取天氣數據的實例詳解內容,有興趣的朋友們學習下。
  • Excel與Python爬取數據,兩者PK,誰優誰劣?
    上圖中是中國證券監督管理委員會中滬市IPO公司的相關信息,我們需要提取其中的表格數據,分別利用Excel與python。ExcelExcel提供兩種獲取網頁數據的方法,第一種是 數據—自網站功能,第二種是Power Query。
  • stata調用python爬取時間數據——借他山之石以攻玉
    該功能使得,我們可以先利用python爬取數據,然後再利用用戶所熟悉的stata去處理數據,因為stata在處理數據方面具有一定的優勢。那麼今天我們就來看看,怎樣利用stata調用python爬取數據,再用stata進行處理?今天試爬的數據是巨潮網上的預約年報的披露時間數據。
  • python實戰案例分享:爬取當當網商品數據(案例)
    在本篇博文中,天善學院特邀講師韋瑋老師會以當當網爬蟲為例,為大家講解如何編寫一個自動爬蟲將當當網的商品數據都爬取下來。,我們需要將爬取到的信息依次展現到屏幕上(當然你也可以將爬取到的信息寫進文件或資料庫中),我們將pipelines.py文件修改為如下所示:# -*- coding: utf-8 -*- # Define your item pipelines here## Don't forget to add your pipeline to
  • python爬蟲之爬取筆趣閣小說
    前言為了上班摸魚方便,今天自己寫了個爬取筆趣閣小說的程序。好吧,其實就是找個目的學習python,分享一下。
  • 使用Python輕鬆獲取股票&基金數據
    AKShare 是基於 Python 的開源金融數據接口庫,目的是實現對股票、期貨、期權、基金、債券、外匯等金融產品和另類數據從數據採集,數據清洗到數據下載的工具,滿足金融數據科學家、數據科學愛好者在數據獲取方面的需求。
  • 用Python進行Web爬取數據
    介紹我們擁有的數據太少,無法建立機器學習模型。我們需要更多數據!如果這句話聽起來很熟悉,那麼你並不孤單!希望獲得更多數據來訓練我們的機器學習模型是一個一直困擾人們的問題。我們無法在數據科學項目中獲得可以直接使用的Excel或.csv文件,對嗎?那麼,如何應對數據匱乏的問題呢?
  • 首發‖全網最適合小白學習的python+數據分析資料,免費領取
    可以想像到未來幾年,眾人趨之若鶩想要踏足數據領域,但迫於門檻過高,投門無路的情景。與其千軍萬馬獨木橋,不如學習就趁現在。但提到數據分析,網課泛濫,資料成災,學習起來毫無頭緒,甚至知識零星,抓不住重點。除此之外設有門檻,對新手小白滿是惡意。
  • Python視頻教程網課編程零基礎入門數據分析網絡爬蟲全套Python...
    本課程為python教程大合集,包含python所有就業方向,每套課程均來自市面上主流培訓機構的原版教程,價值都在數百元以上 每套課程均包含:視頻課程+課件+原始碼 重要:建議根據自己工作方向和需求,重點選擇2到3套課程學精,吃透,然後在工作 重要:零基礎小白建議先選擇零基礎全能篇的一套課程學精
  • 49個python實戰項目列表,得不到就毀掉!!
    這裡整理了49個Python實戰項目列表,都有完整且詳細的教程,你可以從中選擇自己想做的項目進行參考學習練手,你也可以從中尋找靈感去做自己的項目。 python項目列表Python氣象數據分析批量更改Excel文件中200多個工作表的內容批量生成PPT版榮譽證書一鍵抓出PPT中的所有文字快速提取一串字符中的中文
  • 我用 Python 爬取各大板塊 4000+ 個股漲跌幅數據,被驚豔到了!
    大家好,我是東哥,分享一篇超級奈斯的 Excel 繪圖,看到下圖的第一眼確實有被驚豔到。 2月26日大盤雲圖那麼,今天我們試著用 Python 爬取最近交易日的股票數據,並試著用 Excel 簡單繪製上面這個樹狀圖。本文旨在拋磚引玉,吼吼。
  • 18個Python爬蟲實戰案例(已開源)
    稍加修改即可添加到自己的爬蟲中。動態示意圖:爬蟲實戰1、biqukan.py:《筆趣看》盜版小說網站,爬取小說工具第三方依賴庫安裝:pip3 install beautifulsoup4使用方法:python biqukan.py
  • Pyspider框架 —— Python爬蟲實戰之爬取 V2EX 網站帖子
    (http://blog.csdn.net/tzs_1041218129/article/details/52877949)HTTP 599: SSL certificate problem: unable to get local issuer certificate錯誤(http://blog.csdn.net/tzs_1041218129/article/details
  • 用python分析上海二手房數據,用幾十行代碼爬取大規模數據!
    spider_1('http://esf.xian.fang.com/')4、循環翻頁爬取二手房信息考慮到每頁只顯示30條,總共100頁,寫一個循環調用的語句,把100頁的內容全部爬下來# 循環,把第2-100頁全部爬下來page = 1while page 由於房天下的二手房信息是實時更新的,其默認排序是按照發布時間,因此在爬取過程中