首页 > 解决方案 > BeautifulSoup 如何获取包含特定文本的父元素标签?尝试抓取电子邮件但无法获取父元素标签

问题描述

我正在尝试从页面中抓取电子邮件地址,但在获取包含电子邮件“@”符号的父元素时遇到了一些麻烦。电子邮件嵌入在不同的元素标签中,因此我无法将它们挑选出来。我必须浏览大约 50,000 页左右。

url = 'https://sec.report/Document/0001078782-20-000134/#f10k123119_ex10z22.htm'

以下是一些示例(一对来自我必须抓取的不同页面):

<div style="border-bottom:1px solid #000000">**dbrenner@umich.edu**</div>

<div class="f3c-8"><u**>Bob@LifeSciAdvisors.com**</u></div>

<p style="margin-bottom:0pt;margin-top:0pt;;text-indent:0pt;;font-family:Arial;font-size:11pt;font-weight:normal;font-style:normal;text-transform:none;font-variant: normal;">Email: **dmoskowitz@biocept.com**; Phone: 858-320-8244</p>

<td class="f8c-43">E-mail: <u>jcohen@2020gene.com</u></td>

<p class="f7c-4">Email: jcohen@2020gene.com</p>

我试过的:

  1. 我尝试 find_all('div') 来获取所有 div 的 ResultSet 以获取其中包含“@”符号的那些。
div = page.find_all('div')
for each in div:
    if '@' in each.text: 
        print(each.text)

当我这样做时,由于正文位于“div”中,它打印了整个页面。失败。由于电子邮件嵌入在不同的标签中,这种方法似乎效率低下

  1. 使用正则表达式。我尝试使用正则表达式来挑选电子邮件,但它会得到一堆不可用的文本,我必须手动拆分、替换字符等。这似乎是一项艰巨的任务,要经历所有不同的场景。
    import re
    emails = re.findall('\S+@\S+', str(page))
    for each in emails:
        print(each)

这样做给了我这样的东西:

hidden;}@media
#000000">dbrenner@umich.edu</div>
#000000">kherman@umich.edu
#000000">spage@fredhutch.org</div>
#000000">mtuck@umich.edu</div>
#000000">jdahlgre@fredhutch.org</div></p>
#000000">lafky.jacqueline@mayo.edu</div></p>
mtuck@umich.edu)</div>
#000000">ctsucontact@westat.com</div>.
href="http://@umich.edu">@umich.edu</a></li><li><a

现在我可以使用 .split('<') 进入并拆分一些文本,然后再次拆分,等等。但它们并不完全相同,因为我必须在每页中抓取 50,000 多页,每页有 100 个条目,所以有很多我不得不刮和考虑。

我尝试在 google 和 stackoverflow 上查找,但我能找到的只是人们在某个元素中寻找文本的解决方案,等等。

我需要的是“如何找到包含电子邮件的父元素

我认为我不需要为此使用 Selenium,因为该问题类似于使用 Beautifulsoup,并且该站点不是 JavaScript 呈现的,除了某些页面是 pdf 之外,这完全是另一个问题。

任何见解,帮助或建议表示赞赏。谢谢。

标签: pythonregexseleniumweb-scrapingbeautifulsoup

解决方案


有两个选项可以搜索包含@符号的文本:

  1. 使用 CSS 选择器:contains(<MY TEXT>)搜索其中包含@符号的文本。

  2. 在方法中使用lambda函数find_all(),并搜索是否@.text().soup

选项1:

from bs4 import BeautifulSoup


html = """<div style="border-bottom:1px solid #000000">**dbrenner@umich.edu**</div>

<div class="f3c-8"><u**>Bob@LifeSciAdvisors.com**</u></div>

<p style="margin-bottom:0pt;margin-top:0pt;;text-indent:0pt;;font-family:Arial;font-size:11pt;font-weight:normal;font-style:normal;text-transform:none;font-variant: normal;">Email: **dmoskowitz@biocept.com**; Phone: 858-320-8244</p>

<td class="f8c-43">E-mail: <u>jcohen@2020gene.com</u></td>

<p class="f7c-4">Email: jcohen@2020gene.com</p>"""

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

for tag in soup.select('*:contains("@")'):
    print(tag.text.strip())

选项 2:

for tag in soup.find_all(lambda t: "@" in t.text.strip()):
    print(tag.text.strip())

推荐阅读