Python 如何获得;“次级UPS”;并连接/加入它们?

Python 如何获得;“次级UPS”;并连接/加入它们?,python,html,beautifulsoup,html-parsing,Python,Html,Beautifulsoup,Html Parsing,我有一个HTML文档需要处理。我用的是“美丽的汤”。现在,我想从该文档中检索一些“subsup”,并将它们加入到一个soup中,以便以后可以将其用作需要soup对象的函数的参数 如果不清楚,我给你举个例子 from bs4 import BeautifulSoup my_document = """ <html> <body> <h1>Some Heading</h1> <div id="first"> <p>A pa

我有一个HTML文档需要处理。我用的是“美丽的汤”。现在,我想从该文档中检索一些“subsup”,并将它们加入到一个soup中,以便以后可以将其用作需要soup对象的函数的参数

如果不清楚,我给你举个例子

from bs4 import BeautifulSoup

my_document = """
<html>
<body>

<h1>Some Heading</h1>

<div id="first">
<p>A paragraph.</p>
<a href="another_doc.html">A link</a>
<p>A paragraph.</p>
</div>

<div id="second">
<p>A paragraph.</p>
<p>A paragraph.</p>
</div>

<div id="third">
<p>A paragraph.</p>
<a href="another_doc.html">A link</a>
<a href="yet_another_doc.html">A link</a>
</div>

<p id="loner">A paragraph.</p>

</body>
</html>
"""

soup = BeautifulSoup(my_document)

# find the needed parts
first = soup.find("div", {"id": "first"})
third = soup.find("div", {"id": "third"})
loner = soup.find("p", {"id": "loner"})
subsoups = [first, third, loner]

# create a new (sub)soup
resulting_soup = do_some_magic(subsoups)

# use it in a function that expects a soup object and calls its methods
function_expecting_a_soup(resulting_soup)
有什么方便的方法吗?如果有比
find()
更好的方法检索“subsups”,我可以使用它。谢谢

更新


Wondercricket建议将包含找到的标记的字符串连接起来,并再次将它们解析为新的BeautifulSoup对象。虽然这是解决问题的一种可能方法,但重新解析可能需要比我希望的更长的时间,尤其是当我想要检索其中的大部分文档,并且有许多这样的文档需要处理时
find()
返回一个
bs4.element.Tag
。有没有一种方法可以在不将
标记转换为字符串并解析字符串的情况下,将多个
标记连接到一个汤中?

您可以使用
findAll
并传入要使用的元素的
id

import bs4

soup = bs4.BeautifulSoup(my_document)

#EDIT -> I discovered you do not need regex, you can pass in a list of `ids`
sub = soup.findAll(attrs={'id': ['first', 'third', 'loner']})

#EDIT -> adding `html.parser` will force `BeautifulSoup` to not auto append `html` and `body` tags.
sub = bs4.BeautifulSoup('\n\n'.join(str(s) for s in sub), 'html.parser')

print(sub)

>>> <div id="first">
<p>A paragraph.</p>
<a href="another_doc.html">A link</a>
<p>A paragraph.</p>
</div>
<div id="third">
<p>A paragraph.</p>
<a href="another_doc.html">A link</a>
<a href="yet_another_doc.html">A link</a>
</div>
<p id="loner">A paragraph.</p>
导入bs4
soup=bs4.BeautifulSoup(我的文档)
#编辑->我发现您不需要正则表达式,您可以传入一个'id'列表`
sub=soup.findAll(attrs={'id':['first','third','loner']})
#编辑->添加'html.parser'将强制'BeautifulSoup'不自动附加'html'和'body'标记。
sub=bs4.BeautifulSoup('\n\n'.join(在sub中s的str),'html.parser')
打印(sub)
>>> 
一段

一段

一段

段落

将完全满足您的要求,作为奖励,您将获得性能提升,因为它将完全解析您希望它解析的内容,而不是完整的文档树:

from bs4 import BeautifulSoup, SoupStrainer

parse_only = SoupStrainer(id=["first", "third", "loner"])
soup = BeautifulSoup(my_document, "html.parser", parse_only=parse_only)
现在,
soup
对象将只包含所需的元素:

<div id="first">
 <p>
  A paragraph.
 </p>
 <a href="another_doc.html">
  A link
 </a>
 <p>
  A paragraph.
 </p>
</div>
<div id="third">
 <p>
  A paragraph.
 </p>
 <a href="another_doc.html">
  A link
 </a>
 <a href="yet_another_doc.html">
  A link
 </a>
</div>
<p id="loner">
 A paragraph.
</p>

但是
sub
是一个字符串对象,不是吗?它不会表现得像汤,对吧?我想如果没有额外的
(…)
,就不可能创建汤,对吗?此外,重复解析和创建新的soup对象需要一些时间。难道不可能用现有的汤来制作这样的汤吗?也就是说,只有一个解析?@geckon
BeautifulSoup
会自动附加
html/body
标记,但是有一种方法可以解决这个问题;我会更新我的答案。至于重复解析,我不确定是否有办法解决这个问题
findAll
返回一个
ResultSet
,它是
list
的子类。为了连接结果,您需要将项目强制转换为
str
,这将取消
BeautifulSoup
状态。我想我毕竟可以接受“附加的”
标记。对于长文档来说,重新解析可能是一个更大的问题,尤其是当我想要检索其中的大部分文档,并且有许多这样的文档需要处理时
find()
返回一个
bs4.element.Tag
。有没有一种方法可以将多个
标记
连接到一个汤中,而不必将
标记
转换为字符串并解析字符串?@Wondercricket我认为使用
SoupStrainer
作为答案更容易。看看,让我知道你的想法。谢谢。听起来很棒,谢谢!是否不仅可以指定
id
s,还可以指定标签?例如,如果我想过滤所有带有
class=“someclass
的段落,但不过滤具有相同类的div?
<div id="first">
 <p>
  A paragraph.
 </p>
 <a href="another_doc.html">
  A link
 </a>
 <p>
  A paragraph.
 </p>
</div>
<div id="third">
 <p>
  A paragraph.
 </p>
 <a href="another_doc.html">
  A link
 </a>
 <a href="yet_another_doc.html">
  A link
 </a>
</div>
<p id="loner">
 A paragraph.
</p>
from bs4 import BeautifulSoup, SoupStrainer, ResultSet

my_document = """
<html>
<body>

    <h1>Some Heading</h1>

    <div id="first">
    <p>A paragraph.</p>
    <a href="another_doc.html">A link</a>
    <p>A paragraph.</p>
    </div>

    <div id="second">
    <p>A paragraph.</p>
    <p>A paragraph.</p>
    </div>

    <div id="third">
    <p>A paragraph.</p>
    <a href="another_doc.html">A link</a>
    <a href="yet_another_doc.html">A link</a>
    </div>

    <p id="loner">A paragraph.</p>

    <p class="myclass">test</p>
</body>
</html>
"""

def search(tag, attrs):
    if tag == "p" and "myclass" in attrs.get("class", []):
        return tag

    if attrs.get("id") in ["first", "third", "loner"]:
        return tag


parse_only = SoupStrainer(search)

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

print(soup.prettify())