python爬蟲之股票數據定向爬取

python爬蟲之股票數據定向爬取

功能描述

  • 目標:獲取上交所和深交所所有股票的名稱和交易的信息
  • 輸出:保存到文件中
  • 技術路線:requests-bs4-re

前期分析

  • 選取原則:股票的信息靜態存在HTML頁面中,非js代碼生成,沒有robots協議限制
  • 選取方法:查看網頁原碼不糾結於某個網站,多找信息源嘗試

沒有成功,價格沒有搜索到
在這裏插入圖片描述
在源碼中搜索價格,不存在

在這裏插入圖片描述
搜索價格沒有
在這裏插入圖片描述
沒有找到相關的價格信息
在這裏插入圖片描述
沒有找到相關價格信息
在這裏插入圖片描述

沒有找到相關的價格信息
在這裏插入圖片描述
多此嘗試之後,發現基本上都沒有找到,於是找教程推薦的
百度股票,已經不見了
在這裏插入圖片描述

  • 總結:個人觀點,股票價格這種實時更新的數據怎麼會寫在網頁,大部分應該都是寫在js中,然後又服務器發送相關數據,但是仍舊不失爲一個練習的思路,還是來分析一下吧

教程提供的信息:

  • 關於單個股票的信息

    • 點擊每個股票的連接,發現會出現相關的跳轉,反映在網址上的變化就是多了幾個關鍵字
    • 思路:獲取每個股票的標號,輸入到對應的網址中,即可獲得相關股票的實時價格

在這裏插入圖片描述

  • 通過東方財富網獲取所有股票的序號

在這裏插入圖片描述

  • 東方財富網的股票的序號

從圖上就可以看出,是在對應的a標籤中,可以採用正則表達式進行篩選r’[zh|sh]\d{6}’
在這裏插入圖片描述

程序編寫

  • 第一步,編寫相關的整體步驟
    • 從東方財富網獲取股票的列表 getHTMLText(url)
    • 根據股票列表逐個到百度股票中獲取個股的信息 getStockList(lst,stockURL)
    • 將結果存儲到文件中 getStockInfo(lst,stockURL,fpath)
    • main函數將所有的函數連接起來
import requests
import re
from bs4 import BeautifulSoup

# 獲取相關網頁的html文件
def getHTMLText(url):
    return''

# 獲取所有股票的序號
def getStockList(lst,stockURL):
    return ''

# 獲取所有股票的價格
def getStockInfo(lst,stockURL,fpath):
    return ''


def main():
    stock_list_url = 'http://quote.eastmony.com/stocklist.html'
    # 獲取股票信息序號的網站
    stock_info_url = 'https://gupiao.baidu.com/stock/'
    # 獲取單個股票的價格的網頁
    output_file = 'D://SpiderTest//BaiduStockInfo.txt'
    # 文件保存的連接
    slist = []
    getStockList(slist,stock_info_url)
    getStockInfo(slist,stock_info_url,output_file)
    
main()
  • 第二步,逐步完善各個步驟

    • 總是必須的獲取相關頁面的代碼
def getHTMLText(url):
    try:
        r = requests.get(url)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return''
  • 獲取相關的股票列表

這裏有值得學習的東西,先獲取所有的a標籤,然後再逐個進行排除,如果是a標籤,那就添加,不是那就跳過當前的循環,學會用try——except語句

def getStockList(lst,stockURL):
    html =  getHTMLText(stockURL)
    soup = BeautifulSoup(html,'html.parser')
    a = soup.find_all('a')
    for i in  a:
        try:
            href = i.attrs['href']
            lst.append(re.findall(r'[s][hz]\d{6}',href))
        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':'bets-name'})
            # 結合屬性和名稱,獲取特定的標籤

            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')
        except:
            traceback.print_exc()
         
            continue
  • 這裏寫的還是很好看的,分析一下,首先,看下圖,百度股市通中,某單股的原碼
  • 清晰可見,關於股票的信息都在對應的< div > … < /div >標籤中,並且屬性中的class是極特殊的class = ‘stock-bets’的
  • 而在< div > … < /div >的標籤中的,a標籤的值在對應的就是對應的信息,不同的信息他的屬性又是不同
  • 在其子標籤中dt和dd標籤有都含有所有與該股票相關的信息
    在這裏插入圖片描述
  • 第一步,先獲取最外層最特殊的div標籤,並且說明屬性
  stockInfo = soup.find('div',attrs={'class':'stock-bets'})
            # 結合屬性和名稱,獲取特定的標籤
  • 第二步,提取div標籤的具有相關信息屬性的標籤,這個屬性,就說明了這個標籤代表的內容就是名字或者對應的信息
    • 注意:這裏有一個注意點,這裏標籤的text屬性,不是對應的string屬性,text是輸出所有的子節點和自身的string內容,用空格連接
      。string僅僅輸出當前節點的string內容,如果有字節點,那就輸出None
      詳見 https://www.cnblogs.com/gl1573/archive/2018/11/14/9958716.html
   name = stockInfo.find_all(attrs={'class':'bets-name'})[0]
   infoDict.update({'股票名稱':name.text.split()[0]})
  • 第三步,提取所有的dd標籤和dt標籤,二者的數量相同,並作爲鍵值對進行保存
  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
  • 第四步,採用IO流進行寫入,注意類型的轉換
  with open(fpath,'a',encoding = 'utf-8') as f:
                f.write(str(infoDict) + '\n')
  • 最後一步,就是異常的處理,調用traceback庫,進行異常的處理
  except:
            traceback.print_exc()
            continue
最後一步,代碼的優化
  • 爲了創造一個更好的用戶體驗,就創建了寫入一個會實時顯示進度的語塊
  count = count + 1
  print('\r 當前進度:{:.2f}%'.format(count * 100 / len(lst)),end = "")

‘\r’會將輸出的光標移到開頭,覆蓋原來的輸出

總結
  • 關於搜索特定的標籤,不僅僅是結合標籤的名稱,更是要結合標籤的屬性,通過屬性和名稱可以很好的對某一個標籤進行定位
  • 關於try—except的處理,要知道引用traceback庫函數,會反應出報錯對的地方,不然不知道哪裏出錯很鬱悶
  • 有一種設想,從一個網站爬取一定的數據或者項目序列,可以連續的爬取多個同類的網站
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章