如何从晨星上抓取数据

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)

如何提取该图的所有数据点?

chi*_*n88 5

似乎可以从 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 个请求中,查看“预览”窗格,您将在其中看到数据。

在此输入图像描述

这是最终的输出/图表:

在此输入图像描述