为啥当我使用 BeautifulSoup 遍历我的文件时会得到相同的值?

Posted

技术标签:

【中文标题】为啥当我使用 BeautifulSoup 遍历我的文件时会得到相同的值?【英文标题】:Why do I get the same value when I am iterating through my file with BeautifulSoup?为什么当我使用 BeautifulSoup 遍历我的文件时会得到相同的值? 【发布时间】:2022-01-18 02:04:46 【问题描述】:

我想在一个 XML 文件中拆分一些多值属性。

这是最新报道的内容:

 <GenericItem html='ID: AAA1&lt;br/&gt;Age: 12&lt;br/&gt;Name: Baryk &lt;'>
   Employee:
</GenericItem>
<GenericItem html='ID: AAA2&lt;br/&gt;Age: 16&lt;br/&gt;Name: Nils &lt;'>
   Employee:
</GenericItem>
<GenericItem html='ID: AAA3&lt;br/&gt;Age: 18&lt;br/&gt;Name: Sarah &lt;'>
   Employee:
</GenericItem>

这是我的python脚本的内容:

from bs4 import BeautifulSoup
soup = BeautifulSoup(open('NewestReport.xml', 'r'), 'lxml-xml')
br = soup.find_all("GenericItem")
for i in br:
    for i in soup.find("GenericItem").get("html").split("<br/>"):
        print(i.split(":")[1].replace("<", "").strip())

使用这种语法,我收到了相同的值,所以它只打印出 Baryk 的值,其余的都没有。有什么我可以修复的,以便它移动到下一个数据?

【问题讨论】:

预期输出是什么? 【参考方案1】:

注意 正如 Alex Viscreanu 所说,您的代码中首先要处理一些事情 - 这是一种替代方法。

我建议使用 lxml 解析器和 css selectors 来选择元素 - 以下迭代将打印来自每个 GenericItem 的所有值:

for i in soup.select("GenericItem"):
    for e in i.get("html").split("<br/>"):
        print(e.split(":")[1].replace("<", "").strip())

--->
AAA1
12
Baryk
AAA2
16
Nils
AAA3
18
Sarah

要获得更多结构化数据,您可以创建一个字典列表:

data = []

for i in soup.select("GenericItem"):
    t=
    for d in i.get("html").split("<br/>"):
        c=d.split(":")
        k=c[0]
        v=c[1].strip(' |<')
        t[k]=v
    data.append(t) 

示例

from bs4 import BeautifulSoup
xml="""<GenericItem html='ID: AAA1&lt;br/&gt;Age: 12&lt;br/&gt;Name: Baryk &lt;'>
   Employee:
</GenericItem>
<GenericItem html='ID: AAA2&lt;br/&gt;Age: 16&lt;br/&gt;Name: Nils &lt;'>
   Employee:
</GenericItem>
<GenericItem html='ID: AAA3&lt;br/&gt;Age: 18&lt;br/&gt;Name: Sarah &lt;'>
   Employee:
</GenericItem>"""

soup = BeautifulSoup(xml, 'lxml')

data = []

for i in soup.select("GenericItem"):
    t=
    for d in i.get("html").split("<br/>"):
        c=d.split(":")
        k=c[0]
        v=c[1].strip(' |<')
        t[k]=v
    data.append(t)

data

输出

['ID': 'AAA1', 'Age': '12', 'Name': 'Baryk',
 'ID': 'AAA2', 'Age': '16', 'Name': 'Nils',
 'ID': 'AAA3', 'Age': '18', 'Name': 'Sarah']

【讨论】:

【参考方案2】:

您的代码有两个主要问题

    您将在第二个循环中覆盖第一个循环的 i 值 您每次都调用find("GenericItem"),而不是仅使用您之前保存在br 变量中的结果

我认为只要稍微像这样修复它就可以达到您的预期

from bs4 import BeautifulSoup

document = BeautifulSoup(open('NewestReport.xml', 'r'), 'lxml-xml')
items = soup.find_all("GenericItem")

for item in items:
    for line in item.get("html").split("<br/>"):
        print(line.split(":")[1].replace("<", "").strip())

虽然如果您更清楚自己想要达到的目标,我们或许可以为您提供更好的解决方法

文档链接:

https://www.crummy.com/software/BeautifulSoup/bs4/doc/#find-all

【讨论】:

请检查示例 - 没有定义 soup

以上是关于为啥当我使用 BeautifulSoup 遍历我的文件时会得到相同的值?的主要内容,如果未能解决你的问题,请参考以下文章

BeautifulSoup 循环没有遍历其他节点

为啥 BeautifulSoup 将 <html><body><p> 添加到我的结果中?

如果我们可以使用 Selenium,为啥还需要像 BeautifulSoup 这样的解析器?

为啥我在 Python 中使用 BeautifulSoup 得到“'ResultSet' 没有属性 'findAll'”?

使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解(新手必学)

为啥 BeautifulSoup 与“从未检索到任务异常”相关?