在 BeautifulSoup 抓取之后从 Python 中的列表中提取数据,并创建 Pandas 表

Posted

技术标签:

【中文标题】在 BeautifulSoup 抓取之后从 Python 中的列表中提取数据,并创建 Pandas 表【英文标题】:Extracting data from list in Python, after BeautifulSoup scrape, and creating Pandas table 【发布时间】:2020-12-28 06:23:51 【问题描述】:

我学习 Python 的基础知识已经有一段时间了,并认为我会继续尝试将一些东西放在一起,但似乎遇到了一个绊脚石(尽管到处寻找我可能的地方会出错)。

我正在尝试从这里抢一张桌子:https://www.oddschecker.com/horse-racing/2020-09-10-chelmsford-city/20:30/winner

现在我意识到该表并未列出正常 html 的典型程度,因此尝试使用 Pandas 抓取它不会产生结果。因此深入研究 BeautifulSoup 以尝试获得结果。

似乎我需要的所有数据都在“diff-row evTabRow bc”类中,因此写了以下内容:

url = requests.get('https://www.oddschecker.com/horse-racing/2020-09-10-haydock/14:00/winner')
soup = BeautifulSoup(url.content, 'lxml')
table = soup.find_all("tr", class_="diff-row evTabRow bc")

这似乎将每匹马和我需要的所有相应数据放入一个列表中。在这个列表中,我只需要某些位,即马名的“data-name”和当前赔率的“data-odig”。

我认为可能有某种方法可以从列表中提取数据以构建列表列表,然后在 Pandas 中构建一个数据框,但我可能完全错了。

【问题讨论】:

【参考方案1】:

您要查找的数据在行标签

和单元格标签 中。

问题是不是所有的

都是有用的,所以你必须跳过那些。
import pandas as pd

from bs4 import BeautifulSoup
import requests

url   = requests.get('https://www.oddschecker.com/horse-racing/thirsk/13:00/winner')
soup  = BeautifulSoup(url.content, 'lxml')
rows = soup.find_all("tr", class_="diff-row evTabRow bc")

my_data = []
for row in rows:
    horse = row.attrs['data-bname']

    for td in row:
        if td.attrs['class'][0] != 'np':
            continue #Skip

        bookie = td['data-bk']
        odds   = td['data-odig']
        my_data.append(dict(
            horse  = horse,
            bookie = bookie,
            odds   = odds
        ))

df = pd.DataFrame(my_data)
print(df)

这将为您提供所需的内容:

          horse bookie  odds
0    Just Frank     B3  3.75
1    Just Frank     SK  4.33
2    Just Frank     WH  4.33
3    Just Frank     EE  4.33
4    Just Frank     FB   4.2
..          ...    ...   ...
268     Tommy R     RZ    29
269     Tommy R     SX    26
270     Tommy R     BF  10.8
271     Tommy R     MK    41
272     Tommy R     MA    98

[273 rows x 3 columns]

【讨论】:

【参考方案2】:

您可以使用 BeautifulSoup 对象 .attrs 属性访问任何 <tr> 属性。

一旦你有了table,循环遍历每个条目,提取你想要的属性作为字典列表。然后使用结果列表初始化 Pandas 数据框。

horse_attrs = list()

for entry in table:
    attrs = dict(name=entry.attrs['data-bname'], dig=entry.attrs['data-best-dig'])
    horse_attrs.append(attrs)

df = pd.DataFrame(horse_attrs)

df
                name   dig
0         Las Farras  9999
1         Heat Miami  9999
2        Martin Beck  9999
3             Litran  9999
4      Ritmo Capanga  9999
5      Perfect Score  9999
6   Simplemente Tuyo  9999
7            Anpacai  9999
8          Colt Fast  9999
9         Cacharpari  9999
10        Don Leparc  9999
11   Curioso Seattle  9999
12       Golpe Final  9999
13       El Acosador  9999

注意事项:

您提供的网址对我不起作用,但这个类似的网址对我有用:https://www.oddschecker.com/horse-racing/palermo-arg/21:00/winner 我没有看到你提到的确切属性(data-namedata-odig),所以我使用了类似名称的属性。我对赛马知之甚少,不知道这些是否有用,但此答案中的方法应该允许您选择任何可用的属性。

【讨论】:

非常感谢安德鲁,非常感谢。我唯一的问题是,例如,每个博彩公司在 中都有一个唯一标识符,即 data-bk="PP" 这意味着 PaddyPower 是博彩公司,随后是 data-odig 中的赔率。在获取博彩公司名称以将其与给定赔率相关联方面,我将如何工作,即在表格 PP 赔率中,然后在所有列中。谢谢 不客气。如果<td><tr> 中,您可以使用.children 获取其属性。如果您需要比这更具体的帮助,我建议您打开一个单独的问题。 【参考方案3】:

如果是网络抓取,您可以采用将数据存储为各种变量的方法:

l = []
for thing in elements:
    var1 = ...  # however you extract it
    var2 = ...

    l.append('column1_name': var1, 'column2_name': var2)

df = pd.DataFrame(l)

如何从 HTML 元素中选择数据取决于您(考虑选择td?)。

【讨论】:

以上是关于在 BeautifulSoup 抓取之后从 Python 中的列表中提取数据,并创建 Pandas 表的主要内容,如果未能解决你的问题,请参考以下文章

用beautifulsoup4从天才网站上抓取评论

有人使用 Beautifulsoup 从亚马逊抓取成功吗?

BeautifulSoup 使用循环从多个 div 中抓取信息到 JSON

使用 python 3 和 beautifulsoup 从亚马逊抓取图像

使用 Beautifulsoup 和 Python 从 CSV 中抓取多个 URL

如何使用 beautifulsoup 从 html 页面中抓取纬度/经度数据