【问题标题】:create a dictionary or dataframe out of html that has no class keywords用没有类关键字的 html 创建一个字典或数据框
【发布时间】:2021-02-19 20:49:48
【问题描述】:

我每次进行交易时都会收到来自银行的交易电子邮件。它以 html 格式出现。我希望能够从 html 内容中获取某些信息,例如确认号码、日期、金额等。

我尝试使用正则表达式提取和 BeautifulSoup,但结果丑陋且笨拙。例如,html 代码没有任何有用的属性,因此使用属性过滤器进行 find() 并不容易。见下面html代码的sn-p:

<table style="border: 1px solid black; border-collapse: collapse">
    <tbody>
        <tr>
            <td colspan="2" style="border:1px solid black;padding:3px">
                <center>
                    <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                        <b>
                            Transfer Money Details
                        </b>
                    </font>
                </center>
            </td>
        </tr>
        <tr>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Confirmation Number
                </font>
            </td>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    1594379907846
                </font>
            </td>
        </tr>
        <tr>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Transaction Date and Time
                </font>
            </td>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Friday, Jul 10 2020; 07:18:54 PM (GMT +8)
                </font>
            </td>
        </tr>
        <tr>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Transfer From
                </font>
            </td>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    XXXX-XXX-247 (PESO SAVINGS)
                </font>
            </td>
        </tr>
        <tr>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Transfer To
                </font>
            </td>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    XXXX-XXX-545
                </font>
            </td>
        </tr>
        <tr>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Amount
                </font>
            </td>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    PHP 1,200.00
                </font>
            </td>
        </tr>
        <tr>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Service Fee
                </font>
            </td>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    PHP 0.00
                </font>
            </td>
        </tr>
        <tr>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Total Amount
                </font>
            </td>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    PHP 1,200.00
                </font>
            </td>
        </tr>
        <tr>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Notes
                </font>
            </td>
            <td style="border: 1px solid black; padding: 3px">
                <font color="#000000" face="arial" style="FONT-SIZE:10pt">
                    Mask filters
                </font>
            </td>
        </tr>
    </tbody>
</table>

我希望能够拥有如下所示的数据框或字典:

{
'Confirmation Number': '1594379907846',
'Transaction Date and Time': 'Friday, Jul 10 2020; 07:18:54 PM (GMT +8)',
'Transfer From': 'XXXX-XXX-247 (PESO SAVINGS)'
    ... and so on
}

我的代码:

def get_content(html_content):
  soup = BeautifulSoup(html_content, 'html.parser')
  rows = soup.find_all('tr')

  content_ls = []
  trans_details = {}
  for row in rows:
    cells = row.findChildren('td')
    for cell in cells:
      content_ls.append(cell.getText())

  trans_details['Confirmation Number'] = content_ls[2]
  trans_details['Date_Time'] = content_ls[4]
  trans_details['From'] = content_ls[6]
  trans_details['To'] = content_ls[8]
  trans_details['Amount'] = content_ls[10]
  trans_details['Notes'] = content_ls[12]

  return trans_details

产生这个字典:

{'Amount': 'PHP 1,200.00',
 'Confirmation Number': '1594379907846',
 'Date_Time': 'Friday, Jul 10 2020; 07:18:54 PM (GMT +8)',
 'From': 'XXXX-XXX-247 (PESO SAVINGS)',
 'Notes': 'PHP 0.00',
 'To': 'XXXX-XXX-545'}

有没有更优雅和 Pythonic 的方法?

最终,我想生成一个 DataFrame,其中包含“确认编号”、“交易日期和时间”等列。

谢谢

【问题讨论】:

  • 您能否扩展 HTML 示例以在输出中包含您想要的所有数据?更优雅的方式是什么意思?首先向我们展示您的代码。
  • 将表格元素保存到熊猫中。然后,您需要有一个列表,如果列值与它们匹配,则该列表将包含您的实体名称,然后存储这些行结果。
  • 我会从dfs = pd.read_html(html_string) 开始,然后像@Pygirl 所说的那样从那里开始
  • 这个例子看起来很简单。这是一个带有键和值的表格行,它们都很容易提取,因为它们是行中唯一的文本,并且每个都在其自己的 &lt;td&gt; 元素中。我不明白它怎么能比这容易得多。因此,您只需找到所有表格行,从第一个和第二个 &lt;td&gt; 元素中获取所有文本,这将为您提供一个键/值对字典。然后,您只需在该字典中查找“确认号”。如果其他值具有相似的结构,那么您的状态就很好。 BS 应该很适合这个。
  • 访问stackoverflow.com/questions/6325216/… 尝试了解etree

标签: python beautifulsoup


【解决方案1】:

你可以做的是使用lxml lib。它允许您使用 xpath 来查找元素。 这是一种使用您提供的 HTML 提取信息的方法。

def parse(html):
    root = etree.fromstring(html)
    trs = root.xpath("//tr")
    result = dict()
    for tr in trs:
        fonts = tr.xpath(".//font")
        key = fonts[0].text.strip()
        value = fonts[1].text.strip()
        result[key] = value

    return result

【讨论】:

  • @gio888,这里的 TOTO 代码为您提供了我在评论中谈到的字典。
猜你喜欢
  • 1970-01-01
  • 2022-09-28
  • 2017-03-02
  • 2022-11-15
  • 2019-03-15
  • 2018-09-21
  • 2017-01-15
  • 2021-09-22
  • 2017-10-16
相关资源
最近更新 更多