爬取 Yahoo 股市即时股价
这篇文章会使用 Python 的 Requests 函数库,前往 Yahoo 股市的页面,实作从网页 HTML 里,爬取指定上市公司股票即时股价的网络爬虫。
本篇使用的 Python 版本为 3.7.12,所有范例可使用 Google Colab 实作,不用安装任何软件 ( 参考:使用 Google Colab )
Yahoo 奇摩即时股价
通常比较大型的数据分析公司要取得即时股价信息,会串接台湾证券交易所的即时股价 API,进一步得到即时信息,但相对必须支付年费,因此,如果是个人或作为练习使用,可以前往“Yahoo 股市”,透过静态网页爬虫的方法,取得某支股票的即时股价。
打开 Yahoo 股市网页后,在搜索字段输入指定的股票名称或代号,就能搜索出对应的股票,本篇文章搜索“台积电”作为范例。
Yahoo 股市:https://tw.stock.yahoo.com/
确认抓取数据的 HTML 位置
打开台积电即时股价的网页后,目标要抓取“股票名称”、“即时价格”和“涨跌幅”( 下图红色框的内容 )
将鼠标移到台积电名称的上方,按下右键,选择“检查”,查看该名称在 HTML 里的位置和长相。
点击检查后,Chrome 浏览器会打开“开发者工具”,工具里 Elements 页签会显示网页目前的 HTML 结构,从中可以看到一个 id 为 main-0-QuoteHeader-Proxy 的 div 里,包含 h1 的股票名称标题,以及相关的股价信息。
正常的网页里,id 和 h1 都只会存在一个 ( 不会有两个重复的 id 或重复的 h1 )。
再打开网页的源代码 ( 鼠标在网页的任意位置按下右键,选择“检视网页源代码”),检查源代码里是否包含这些信息,检查后发现源代码内也有这些内容,所以就能够用静态网页的爬虫抓取数据。
如果网页源代码和开发者工具的 HTML 的内容不同,表示这个网页可能是“动态”产生内容,就必须要用动态网页的爬虫方式爬取数据。
爬取即时股价
从源代码里看到 id、class 和 h1 之后,就可以使用 requests 与 Beautiful Soup 函数库爬取所需的内容,当中使用了 try...except 的方式,判断是否具有代表上涨或下跌的 class 名称,下方的程序执行后,就会印出股票名称、股价以及涨跌幅。
参考:Requests 函数库、Beautiful Soup 函数库、例外处理 ( try、except )、文字格式化 f-string
import requests
from bs4 import BeautifulSoup
url = 'https://tw.stock.yahoo.com/quote/2330' # 台積電 Yahoo 股市網址
web = requests.get(url) # 取得網頁內容
soup = BeautifulSoup(web.text, "html.parser") # 轉換內容
title = soup.find('h1') # 找到 h1 的內容
a = soup.select('.Fz(32px)')[0] # 找到第一個 class 為 Fz(32px) 的內容,如果出現錯誤,可以使用 .Fz\(32px\) 轉義
b = soup.select('.Fz(20px)')[0] # 找到第一個 class 為 Fz(20px) 的內容,如果出現錯誤,可以使用 .Fz\(20px\) 轉義
s = '' # 漲或跌的狀態
try:
# 如果 main-0-QuoteHeader-Proxy id 的 div 裡有 C($c-trend-down) 的 class
# 表示狀態為下跌
if soup.select('#main-0-QuoteHeader-Proxy')[0].select('.C($c-trend-down)')[0]:
s = '-'
except:
try:
# 如果 main-0-QuoteHeader-Proxy id 的 div 裡有 C($c-trend-up) 的 class
# 表示狀態為上漲
if soup.select('#main-0-QuoteHeader-Proxy')[0].select('.C($c-trend-up)')[0]:
s = '+'
except:
# 如果都沒有包含,表示平盤
s = '-'
print(f'{title.get_text()} : {a.get_text()} ( {s}{b.get_text()} )') # 印出結果
同时爬取多支股票的股价
顺利爬取即时股价后,搭配 concurrent.futures 内建函数库,就能够同时 ( 接近同时 ) 抓取多支股票的股价。
import requests
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor
# 建立要抓取的股票網址清單
stock_urls = [
'https://tw.stock.yahoo.com/quote/2330',
'https://tw.stock.yahoo.com/quote/0050',
'https://tw.stock.yahoo.com/quote/2317',
'https://tw.stock.yahoo.com/quote/6547'
]
# 將剛剛的抓取程式變成「函式」
def getStock(url):
web = requests.get(url)
soup = BeautifulSoup(web.text, "html.parser")
title = soup.find('h1')
a = soup.select('.Fz(32px)')[0] # 如果出現錯誤,可以使用 .Fz\(32px\) 轉義
b = soup.select('.Fz(20px)')[0] # 如果出現錯誤,可以使用 .Fz\(20px\) 轉義
s = ''
try:
if soup.select('#main-0-QuoteHeader-Proxy')[0].select('.C($c-trend-down)')[0]:
s = '-'
except:
try:
if soup.select('#main-0-QuoteHeader-Proxy')[0].select('.C($c-trend-up)')[0]:
s = '+'
except:
state = ''
print(f'{title.get_text()} : {a.get_text()} ( {s}{b.get_text()} )')
executor = ThreadPoolExecutor() # 建立非同步的多執行緒的啟動器
with ThreadPoolExecutor() as executor:
executor.map(getStock, stock_urls) # 開始同時爬取股價
小结
这篇教学整合了三种函数库的应用,包含 Requests、Beautiful Soup 和 concurrent.futures,除了单纯地取得静态网页股价,也可以同时抓取多个网页的信息,最后,也可以尝试看看配合 CSV 函数库,就能将抓取的股价,存到 CSV 文件里。
微信扫码关注
抖音扫码关注