【问题标题】:How to parse this? Trying to pull data from non-HTML webpage using BeautifulSoup and Python如何解析这个?尝试使用 BeautifulSoup 和 Python 从非 HTML 网页中提取数据
【发布时间】:2016-12-15 20:01:10
【问题描述】:

BeautifulSoup & HTML 新手,我以前从未见过这种类型的页面。我正在尝试从威斯康星州戴恩县的 2008 年总统竞选中提取数据。

链接:https://www.countyofdane.com/clerk/elect2008d.html

总统竞选的数据似乎在硬编码表中?它不存储在 HTML 标记之间,或者我之前遇到的任何内容之间。

我可以以某种方式通过迭代< !-- #--> 来提取数据吗?我应该将页面保存为 HTML 文件并在表格周围添加一个 body 标记以便更容易解析吗?

【问题讨论】:

  • 此时您正在解析文本。 BeautifulSoup 不会有任何帮助。解析实际数据将相当简单,但对角线标题将......具有挑战性。
  • 一旦你在<pre></pre>标签之间有了文本,你可能最好用正则表达式解析。
  • @kindall 从技术上讲解析标题并不复杂。首先,您必须测量它们占用了多少行。然后,您可以测量每行必须在右侧添加多少空间。然后列开始的每个字母都是一个名称,列末尾的每个字母都是另一个名称。列是带有---- 的标记。嗯,不,这很复杂,但并非不可能。

标签: python html beautifulsoup html-parsing


【解决方案1】:

这个问题实际上来自 文本解析,因为表格是 纯文本pre 元素内的。

您可以从这里开始。这个想法是通过使用----- 标题和表格后面的空行来检测表格的开头和结尾。大致如下:

import re

from bs4 import BeautifulSoup
import requests
from ppprint import pprint

url = "https://www.countyofdane.com/clerk/elect2008d.html"
response = requests.get(url)

soup = BeautifulSoup(response.content, "html.parser")

is_table_row = False

tables = []
for line in soup.pre.get_text().splitlines():
    # beginning of the table
    if not is_table_row and "-----" in line:
        is_table_row = True
        table = []
        continue

    # end of the table
    if is_table_row and not line.strip():
        is_table_row = False
        tables.append(table)
        continue

    if is_table_row:
        table.append(re.split("\s{2,}", line))  # splitting by 2 or more spaces

pprint(tables)

这将打印一个列表列表 - 一个包含每个表的数据行的子列表:

[
    [
        ['0001 T ALBION WDS 1-2', '753', '315', '2', '4', '1', '0', '5', '2', '0', '1'],
        ['0002 T BERRY WDS 1-2', '478', '276', '0', '0', '0', '0', '2', '0', '0', '1'],
        ...
        ['', 'CANDIDATE TOTALS', '205984', '73065', '435', '983', '103', '20', '1491', '316', '31', '511'],
        ['', 'CANDIDATE PERCENT', '72.80', '25.82', '.15', '.34', '.03', '.52', '.11', '.01', '.18']],
    [
        ['0001 T ALBION WDS 1-2', '726', '323', '0'],
        ['0002 T BERRY WDS 1-2', '457', '290', '1'],
        ['0003 T BLACK EARTH', '180', '107', '0'],
        ...
    ],
    ...
]

当然,这不包括表格名称和对角线标题,这可能很难获得,但并非不可能。另外,您可能希望将总行与表的其他数据行分开。无论如何,我认为这对您来说是一个很好的开始示例。

【讨论】:

  • 对不起,两个菜鸟问题:1)“.pre”在“for line in soup.pre.get_text().splitlines():”中有什么作用 2)我正在努力进一步 ppprint ,你能指出我的文档吗?想确保我和你看的一样
  • @kfish15 当然,没问题。 1)soup.pre 等价于soup.find("pre")。 2) pprint() 仅用于漂亮的打印,在代码示例中使用它没有任何功能目的。谢谢。
猜你喜欢
  • 2013-11-15
  • 2013-01-29
  • 1970-01-01
  • 2012-04-04
  • 2012-05-11
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2019-05-24
相关资源
最近更新 更多