股票數據定向爬蟲
來自北理工網絡公開課——Python網絡爬蟲與信息提取
課程鏈接http://open.163.com/movie/2019/5/I/O/MEEMCM1NP_MEF0L2JIO.html
功能描述:
目標:獲取上交所和深交所所有股票的名稱和交易信息
輸出:保存到文件中
技術方案:requests-bs4-re
候選網站:
1、新浪股票:http://finance.sina.com.cn/stock/
2、百度股票:https://gupiao.baidu.com/stock/
選取原則:股票信息靜態存放在HTML頁面中,非js代碼生成,沒有robots協議限制
新浪股票:js代碼生成
百度股票:嵌在html代碼中(更適合定向爬蟲)
確定所有股票列表
使用另一個網站:東方財富網http://quote.eastmoney.com/stock_list.html
程序的結構設計:
1、從東方財富網獲取股票列表
2、根據股票列表逐個到百度股票獲取個股信息
3、將結果存儲到文件中
根據百度股票對個股信息的保留方式,我們考慮採用字典的方式來進行存儲
小結:
非常有特徵的數據,我們可以通過正則表達式來獲取;
存在的區域相對固定,可以用bs,然後再用正則表達式
程序代碼:
import requests
from bs4 import BeautifulSoup
import traceback
import re
#獲得URL對應的頁面
def getHTMLText(url,code='utf-8'):
try:
r=requests.get(url,timeout=30)
r.raise_for_status()
'''
速度提高:編碼識別的優化
r.apparent_encoding是將獲得的html頁面文本內容交給程序來判斷
而r.encoding只是從html的頭文件中解析其用的方式
'''
#r.encoding=r.apparent_encoding
r.encoding=code
return r.text
except:
return ""
#獲得股票的信息列表
def getStockList(lst,stockURL):
html=getHTMLText(stockURL,'GB2312')
soup=BeautifulSoup(html,'html.parser')
#通過觀察東方財富網的源代碼,我們發現我們要找的股票代碼都存在了<a>標籤裏,所以我們需要找到所有的<a>標籤
a=soup.find_all('a')
for i in a:
# 我們找到<a>標籤裏面的href屬性中的最後html前面有股票代碼我們將其提取出來即可
# <a target="_blank" href="http://quote.eastmoney.com/sh201000.html">
# 股票代碼的規律,上交所的爲“sh+6位數字”,深交所的爲“sz+6位數字”
try:
href=i.attrs['href']
lst.append(re.findall(r"[s][hz]\d{6}",href)[0])
except:
continue#出現異常程序繼續執行即可,可能一些匹配出現問題
#獲得每一個個股的股票信息,並將其存在一個文件中
def getStockInfo(lst,stockURL,fpath):
#在百度股票中
count = 0
for stock in lst:
url=stockURL+stock+".html"
html=getHTMLText(url)
try:
if html=="":
continue
#定義一個字典,存儲從頁面中返回的所有的個股信息
infoDict={}
soup=BeautifulSoup(html,"html.parser")
stockInfo=soup.find('div',attrs={'class':'stock-bets'})
name=stockInfo.find_all(attrs={'class':'bets-name'})[0]
#可能待會兒在這出現差錯,是因爲在東方財富網上的有關基金在百度股票網上找不到對應的股票
infoDict.update({'股票名稱':name.text.split()[0]})
keyList=stockInfo.find_all('dt')
valueList=stockInfo.find_all('dd')
for i in range(len(keyList)):
key=keyList[i].text
val=valueList[i].text
infoDict[key]=val#字典的用法
#體驗提高:增加動態進度顯示
with open(fpath,'a',encoding='utf-8') as f:
f.write(str(infoDict)+'\n')
count+=1
print("\r當前進度:{:.2f}%".format(count*100/len(lst)),end="")#\r打印的內容會覆蓋之前的內容
except:
#traceback.print_exc()#知道哪些地方發生了異常,獲得錯誤信息
count+=1
print("\r當前進度:{:.2f}%".format(count * 100 / len(lst)), end="")
continue
if __name__ == '__main__':
stock_list_url="http://quote.eastmoney.com/stock_list.html"#股票列表的網站
stock_info_url='https://gupiao.baidu.com/stock/'
output_file="D://BaiduStockInfo.txt"
slist=[]#存儲股票的信息
getStockList(slist,stock_list_url)
getStockInfo(slist,stock_info_url,output_file)