【问题标题】:Can't locate and capture few fields out of some unstructured html无法从一些非结构化 html 中定位和捕获少数字段
【发布时间】:2021-10-09 07:08:05
【问题描述】:

我正在尝试使用 BeautifulSoup 库从 webpage 中挖出四个字段。很难单独识别这些字段,这就是我寻求帮助的原因。

有时两封电子邮件都存在,但并非总是如此。我使用索引来捕获此示例的电子邮件,但肯定这是最糟糕的想法。此外,通过以下尝试,我只能解析电子邮件的标题,而不是电子邮件地址。

我已经尝试过(最小工作示例):

from bs4 import BeautifulSoup

html = """
  <p>
   <strong>
    Robert Romanoff
   </strong>
   <br/>
   146 West 29th Street, Suite 11W
   <br/>
   New York, New York 10001
   <br/>
   Telephone: (718) 527-1577
   <br/>
   Fax: (718) 276-8501
   <br/>
   Email:
   <a href="mailto:robert@absol.com">
    robert@absol.com
   </a>
   <br/>
   Additional Contact: William Locantro
   <br/>
   Email:
   <a href="mailto:bill@absol.com">
    bill@absol.com
   </a>
  </p>
"""
soup = BeautifulSoup(html,"lxml")
container = soup.select_one("p")
contact_name = container.strong.text.strip()
contact_email = [i for i in container.strings if "Email" in i][0].strip()
additional_contact = [i.strip() for i in container.strings if "Additional Contact" in i.strip()][0].strip('Additional Contact:')
additional_email = [i for i in container.strings if "Email" in i][1].strip()
print(contact_name,contact_email,additional_contact,additional_email)

当前输出:

Robert Romanoff Email: William Locantro Email:

预期输出:

Robert Romanoff robert@absol.com William Locantro bill@absol.com

【问题讨论】:

  • 你能分享一下网址吗?很难给出适用于所有情况的解决方案。
  • 查看编辑@Ram。

标签: python python-3.x web-scraping beautifulsoup


【解决方案1】:

对于更复杂的 html/xml 解析,您应该查看xpath,它允许非常强大的选择器规则。

在 python 中,它在 parsel 包中可用。

from parsel import Selector

html = '...'
sel = Selector(html)
name = sel.xpath('//strong[1]/text()').get().strip()
email = sel.xpath("//text()[re:test(., 'Email')]/following-sibling::a/text()").get().strip()
name_additional = sel.xpath("//text()[re:test(., 'Additional Contact')]").re("Additional Contact: (.+)")[0]
email_additional = sel.xpath("//text()[re:test(., 'Additional Contact')]/following-sibling::a/text()").get().strip()
print(name, email, name_additional, email_additional)
# Robert Romanoff robert@absol.com William Locantro bill@absol.com

【讨论】:

  • 我被你的回答迷住了,所以忘了问re:test()在这里做什么。谢谢。
  • re:test 是一个在目标上执行正则表达式匹配测试的 xpath 函数。函数签名是re:test(target, pattern, flags)。在这种情况下,我们测试.,它指的是“self”(文本节点),我们的模式是"Additional Contact",我们不提供任何标志(或者您可以指定"i" 以忽略大小写)。执行相同功能的另一种方法是使用 contains() 函数:[contains(., "Additional Contact")] - re:test() 只是此功能的更高级版本。
  • 更多关于这个parsel文档:parsel.readthedocs.io/en/latest/…
【解决方案2】:

你可以这样做。

  • 选择包含您需要的数据的&lt;div&gt;
  • 创建上面选定的&lt;div&gt;中存在的数据列表
  • 遍历列表并提取您需要的数据。

代码如下:

from bs4 import BeautifulSoup
import requests

url = 'http://www.nyeca.org/find-a-contractor-by-name/'
r = requests.get(url)
soup = BeautifulSoup(r.text,"lxml")

d = soup.find_all('div', class_='sabai-directory-body')
for i in d:
    x = i.text.strip().split('\n')
    data = [x[0].strip()]
    for item in x:
        if item.startswith('Email'):
            data.append(item.split(':')[1].strip())
        elif item.startswith('Additional'):
            data.append(item.split(':')[1].strip())
    print(data)

提供承包商详细信息列表以及其他详细信息(如果有)。

['Ron Singh', 'rsingh@atechelectric.com']
['George Pacacha', 'Office@agvelectricalservices.com']
['Andrew Drazic', 'ADrazic@atjelectrical.com']
['Albert Barbato', 'Abarbato@abelectriccorp.com']
['Ralph Sica', 'Ralph.Sica@abm.com', 'Henry Kissinger', 'Henry.Kissinger@abm.com']
['Robert Romanoff', 'robert@absoluteelectric.com', 'William Locantro', 'bill@absoluteelectric.com']
.
.

【讨论】:

    【解决方案3】:

    这里有一个解决方案,你可以试一试,

    import re
    
    soup = BeautifulSoup(html, "lxml")
    
    names_ = [
        soup.select_one("p > strong").text.strip(),
        soup.find(text=re.compile("Additional Contact:")).replace('Additional Contact:', '').strip()
    ]
    
    email_ = [i.strip() for i in soup.find_all(text=re.compile("absol"))]
    
    print(" ".join(i + " " + j for i, j in zip(names_, email_)))
    

    Robert Romanoff robert@absol.com William Locantro bill@absol.com
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 2019-12-10
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 2014-10-20
      相关资源
      最近更新 更多