S&P-500、Nasdaq-100成分股股價爬蟲

Tsung-Lun Tsai
5 min readSep 16, 2019

--

首先要取得成分股的清單,S&P-500找不到官方的成分股連結(非官方可能不會定期更新),先用別的替代,Nasdaq就有找到官方資訊。

使用pandas的read_html快速爬取網頁table的內容,再做資料處理對欄位。Nasdaq-100蠻多成分股和S&P-500重合,所以要拿掉重複項:

#爬取成分股清單import pandas as pd
import requests
from io import StringIO
def US_StockList():
#sp-500
link = ‘https://www.slickcharts.com/sp500'
r = requests.get(link)
lines = r.text.replace(‘\r’, ‘’).split(‘\n’)
df = pd.read_html(StringIO(“\n”.join(lines[:])), header=None)[0]
df=df.loc[:,[‘Company’,’Symbol’]]
df=df.rename(columns={‘Company’:’US_StockName’,’Symbol’:’stock_id’})
#Nasdaq-100
link = ‘https://www.nasdaq.com/market-activity/quotes/Nasdaq-100-Index-Components'
r = requests.get(link)
lines = r.text.replace(‘\r’, ‘’).split(‘\n’)
df2 = pd.read_html(StringIO(“\n”.join(lines[:])), header=None)[0]
df2=df2.rename(columns={‘COMPANY NAME’:’US_StockName’,’SECURITY SYMBOL’:’stock_id’})
#合併並拿掉重複項
df3=pd.concat([df,df2])
df4=df3.set_index(‘stock_id’)
df4=df4[~df4.index.duplicated(keep=’first’)]#keep=’first保留重複的首項,另一種是last
return df4
output:成分股清單
output:成分股清單

有了清單後就有爬取的目標了,接下來就是股價資訊爬蟲,Yahoo Finance有提供方便的API:fix-yahoo-finance 0.0.22。

下載說明:https://pypi.org/project/fix-yahoo-finance/

裝完後就可使用套件進行爬蟲,只要設定資料起始日,爬蟲就會依照標的分別爬取起使日至最近一日的股價資訊。存取方式看個人偏好來設定,範例是使用sqlite。

#美股股價爬蟲import pandas as pd
import requests
from pandas_datareader import data as web
import fix_yahoo_finance as yf
import datetime as dt
import sqlite3
import os
from io import StringIO
def crawl_US_Stock(startDate):
#startDate引數決定資料起始日
#導入美股清單
US_Stock_List=US_StockList()
target=US_Stock_List.index
data=[]
for stock_id in target:
try:
df = web.get_data_yahoo(stock_id,startDate,dt.datetime.now())
df[‘stock_id’]=stock_id
df=df.reset_index()
print(stock_id )
data.append(df)
except:
print(‘error’,stock_id )
pass
data=pd.concat(data)
data = data.rename(columns={‘Date’:’date’})
data=data.set_index([‘stock_id’])
data[‘US_StockName’]=US_Stock_List[‘US_StockName’]
data=data.reset_index()
data=data.set_index([‘stock_id’,’date’])
# conn = sqlite3.connect(os.path.join(‘data’, ‘data.db’))
# data.to_sql(‘price_US’,conn,if_exists=’replace’)

return data
crawl_US_Stock(dt.datetime(2000,1,1))
output:成分股股價資訊,少部分股票如BRK.B波克夏B股會抓不到。
output:成分股股價資訊,少部分股票如BRK.B波克夏B股會抓不到,似乎只要有.A或.B的都抓不到。

--

--