Vis*_*ain 3 python beautifulsoup web-scraping
所以我对网络抓取世界还是个新手,到目前为止我只真正使用 beautifulsoup 从网站上抓取文本和图像。我想我应该尝试从图表中刮掉一些数据点来测试我的理解,但我对这张图表有点困惑。
在检查了我想要提取的数据片段的元素后,我看到了这一点:
<span id="TSMAIN">: 100.7490637</span>
问题是,我抓取数据点的最初想法是迭代某种包含所有不同数据点的 id 列表(如果说得通?)。
相反,似乎所有数据点都包含在同一个元素中,并且该值取决于光标在图表上的位置。
id我的问题是,如果我使用 beautifulsoups find 函数并在具有=属性的特定元素中键入TSMAIN,我会得到一个无类型返回,因为我猜测除非我将光标放在实际图表上,否则不会显示任何内容。
代码:
from bs4 import BeautifulSoup
import requests
headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"}
url = "https://www.morningstar.co.uk/uk/funds/snapshot/snapshot.aspx?id=F0GBR050AQ&tab=13"
source=requests.get(url,headers=headers)
soup = BeautifulSoup(source.content,'lxml')
data = soup.find("span",attrs={"id":"TSMAIN"})
print(data)
Run Code Online (Sandbox Code Playgroud)
输出
None
Run Code Online (Sandbox Code Playgroud)
如何提取该图的所有数据点?
似乎可以从 API 中提取数据。唯一的问题是它返回的值与有效负载中输入的开始日期相关。它将开始日期的输出设置为0,然后后面的数字相对于该日期。
import requests
import pandas as pd
from datetime import datetime
from dateutil import relativedelta
userInput = input('Choose:\n\t1. 3 Month\n\t2. 6 Month\n\t3. 1 Year\n\t4. 3 Year\n\t5. 5 Year\n\t6. 10 Year\n\n -->: ')
userDict = {'1':3,'2':6,'3':12,'4':36,'5':60,'6':120}
n = datetime.now()
n = n - relativedelta.relativedelta(days=1)
n = n - relativedelta.relativedelta(months=userDict[userInput])
dateStr = n.strftime('%Y-%m-%d')
url = 'https://tools.morningstar.co.uk/api/rest.svc/timeseries_cumulativereturn/t92wz0sj7c'
data = []
idDict = {
'Schroder Managed Balanced Instl Acc':'F0GBR050AQ]2]0]FOGBR$$ALL',
'GBP Moderately Adventurous Allocation':'EUCA000916]8]0]CAALL$$ALL',
'Mixed Investment 40-85% Shares':'LC00000012]8]0]CAALL$$ALL',
'':'F00000ZOR1]7]0]IXALL$$ALL',}
for k, v in idDict.items():
payload = {
'encyId': 'GBP',
'idtype': 'Morningstar',
'frequency': 'daily',
'startDate': dateStr,
'performanceType': '',
'outputType': 'COMPACTJSON',
'id': v,
'decPlaces': '8',
'applyTrackRecordExtension': 'false'}
temp_data = requests.get(url, params=payload).json()
df = pd.DataFrame(temp_data)
df['timestamp'] = pd.to_datetime(df[0], unit='ms')
df['date'] = df['timestamp'].dt.date
df = df[['date',1]]
df.columns = ['date', k]
data.append(df)
final_df = pd.concat(
(iDF.set_index('date') for iDF in data),
axis=1, join='inner'
).reset_index()
final_df.plot(x="date", y=list(idDict.keys()), kind="line")
Run Code Online (Sandbox Code Playgroud)
输出:
print (final_df.head(5).to_string())
date Schroder Managed Balanced Instl Acc GBP Moderately Adventurous Allocation Mixed Investment 40-85% Shares
0 2019-12-22 0.000000 0.000000 0.000000 0.000000
1 2019-12-23 0.357143 0.406784 0.431372 0.694508
2 2019-12-24 0.714286 0.616217 0.632422 0.667586
3 2019-12-25 0.714286 0.616217 0.632422 0.655917
4 2019-12-26 0.714286 0.612474 0.629152 0.664124
....
Run Code Online (Sandbox Code Playgroud)
为了获得这些 ID,需要对请求进行一些调查。通过这些搜索,我能够找到相应的 id 值,并通过一些尝试和错误来找出值的含义。
使用的那些“备用”ID。这些折线图从哪里获取数据(在这 4 个请求中,查看“预览”窗格,您将在其中看到数据。
这是最终的输出/图表:
| 归档时间: |
|
| 查看次数: |
5614 次 |
| 最近记录: |