網頁

2024年4月16日 星期二

Python:台股ETF爬蟲(2)持股頁面

要了解一檔ETF為何績效好(壞)一個很重要的原因是它的持股,就拿最近AI當家,基本上持有這類股票的ETF績效都不會太差,這篇就接著 Python:台股ETF爬蟲 來講解如何把ETF持股爬下來。

我以 MoneyDJ 網站說明,首先來看看元大S&P500持股頁面,網址是:https://www.moneydj.com/ETF/X/Basic/Basic0007B.xdjhtm?etfid=00646.TW

和淨值頁面https://www.moneydj.com/ETF/X/Basic/Basic0003.xdjhtm?etfid=00646.TW就是差在淨值頁面網址是Basic0003,持股頁面是Basic0007B。

接著一樣用BeautifulSoup把網頁爬下來:

url = 'https://www.moneydj.com/ETF/X/Basic/Basic0003.xdjhtm?etfid=00757.TW'
url = re.sub('[B|b]asic0003', 'Basic0007B', url)
response = requests.get(url)
response.encoding = 'utf-8'
web_content = response.text
soup = BeautifulSoup(web_content, 'lxml')

看一下soup裡面放了哪些東西:

持股表格的id是"ctl00_ctl00_MainContent_MainContent_sdate3",文字屬性就是"資料日期:2024/03/28",可以這麼寫:

# 取出表格文字屬性 
soup.find('div', id='ctl00_ctl00_MainContent_MainContent_sdate3').text

輸出結果:

表格可以這樣取出:

soup.find_all('table', id='ctl00_ctl00_MainContent_MainContent_stable3')[0]

也可以:

soup.select('table')[3]

輸出結果:

最後將這些整理放入變數:

lst = pd.read_html(data.prettify())
df = lst[0]
print(f'{update_str}')
df.head(10)

輸出結果 (因為頁面是前20大持股,我只列出前10筆):

我挑選了六檔ETF當範例,程式如下:

from bs4 import BeautifulSoup
import urllib.request
import pandas as pd
# ETF 名稱
fund_dict = {'國泰北美科技':
'https://www.moneydj.com/ETF/X/Basic/Basic0003.xdjhtm?etfid=00770.TW',
'富邦NASDAQ':
'https://www.moneydj.com/etf/x/basic/basic0003.xdjhtm?etfid=00662.tw',
'元大S&P500':
'https://www.moneydj.com/ETF/X/Basic/Basic0003.xdjhtm?etfid=00646.TW',
'元大全球AI ':
'https://www.moneydj.com/ETF/X/Basic/Basic0003.xdjhtm?etfid=00762.TW',
'國泰費城半導體':
'https://www.moneydj.com/ETF/X/Basic/Basic0003.xdjhtm?etfid=00830.TW',
'統一FANG+':
'https://www.moneydj.com/ETF/X/Basic/Basic0003.xdjhtm?etfid=00757.TW'}
# 取得持股明細
def get_etf_components(url):
url = re.sub('[B|b]asic0003', 'Basic0007B', url)
response = requests.get(url)
response.encoding = 'utf-8'
web_content = response.text
soup = BeautifulSoup(web_content, 'lxml')
update_str = soup.find('div', id='ctl00_ctl00_MainContent_MainContent_sdate3').text
data = soup.find_all('table', id='ctl00_ctl00_MainContent_MainContent_stable3')[0]
lst = pd.read_html(data.prettify())
df = lst[0]
return df.head(10), update_str

for name in fund_dict.keys():
url = fund_dict[name]
compon_df, update_str = get_etf_components(url)
print(f'{name} 持股明細 {update_str}')
print(compon_df.to_string(), '\n')

輸出結果:




沒有留言:

張貼留言