如何从包含请求和 BeautifulSoup4 的动态内容的网站中提取 table 数据?

How to extract table data from website with dynamically content with requests and BeautifulSoup4?

我从该页面提取 table 时遇到一些问题:www.nasdaq.com/market-activity/stocks/aapl/dividend-history

我的代码是:

import requests
from bs4 import BeautifulSoup

headers = {'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'}
page = requests.get("https://www.nasdaq.com/market-activity/stocks/aapl/dividend-history", headers=headers)
soup = BeautifulSoup(page.content, 'html.parser')

table = soup.find('table', attrs={'class':'dividend-history__table'})
table_body = table.find('tbody', attrs={'class': 'dividend-history__table-body'})
data = []
rows = table_body.find('tr', attrs={'class': 'dividend-history__row dividend-history__row--data'})
for row in rows:
    cols = row.find('td')
    cols = [ele.text.strip() for ele in cols]
    data.append([ele for ele in cols if ele]) # Get rid of empty values

他们在 iframe 中有 table。我不确定我做错了什么 - 这是我第一次使用 BeautifulSoup - 我通常使用请求 + xPath 来处理这种事情。

会发生什么?

  1. Table 不在您猜测的 iframe 中。
  2. Table 数据是动态生成的,所以你无法用你的方法获取它
  3. 如果内容是静态的,到这行为止一切都会正常。

看一下 find() 只得到第一次出现的过滤器 - 只有一个 <tr> 而不是你应该使用 find_all()

rows = table_body.find('tr', attrs={'class': 'dividend-history__row dividend-history__row--data'})

您尝试循环一个不可迭代对象:

for row in rows:

find() 相同:

cols = row.find('td')

再次迭代一个不可迭代对象:

cols = [ele.text.strip() for ele in cols]

换一种方式怎么样?

从网站抓取数据的方法多种多样,如果它们处理的是动态数据,您经常会遇到 requests 的限制。

使用网站怎么样api?

有请求和 pandas 可以这么简单:

import requests
import pandas as pd

url = "https://api.nasdaq.com/api/quote/AAPL/dividends?assetclass=stocks"
headers = {"user-agent": "Mozilla/5.0"}

r = requests.get(url, headers=headers)

df = pd.json_normalize(r.json()['data']['dividends']['rows'])
df

输出

exOrEffDate type    amount  declarationDate recordDate  paymentDate

11/06/2020  CASH    [=14=].205  10/29/2020  11/09/2020  11/12/2020
08/07/2020  CASH    [=14=].82   07/30/2020  08/10/2020  08/13/2020
05/08/2020  CASH    [=14=].82   04/30/2020  05/11/2020  05/14/2020
02/07/2020  CASH    [=14=].77   01/28/2020  02/10/2020  02/13/2020
11/07/2019  CASH    [=14=].77   10/30/2019  11/11/2019  11/14/2019