【问题标题】:BeautifulSoup - xml - find_next: limiting to one attributeBeautifulSoup - xml - find_next:限制为一个属性
【发布时间】:2021-12-27 05:57:19
【问题描述】:

感谢任何帮助!使用下面的示例 XML 文件,我得到了不正确的输出。

Incorrect output: 
Emp_F_Name: Jill
Emp_M_Name: H
Emp_L_Name: Jones

Desired output:
Emp_F_Name: Jill
Emp_M_Name: None or NULL
Emp_L_Name: Jones

我不确定为什么 find_next 函数超出了声明的属性(员工)。

   <?xml version="1.0" encoding="utf-8"?>
    <org value="Tech">
    <employee>
    <name>
    <family>Jones</family>
    <given>Jill</given>
    </name>
    </employee>
    <manager>
    <name>
    <family>Fisher</family>
    <given>Junior</given>
    <given>H</given>
    </name>
    </manager>
    </org>

这是我正在使用的代码。

employee = soup.find("employee")

for i in employee.find_all('name'):
    fname = employee.find('given')
    print("Emp_F_Name: ", fname.get_text())
    
    mname = fname.find_next('given')
    print("Emp_M_Name: ", mname.get_text())
    
    lname = employee.find('family')
    print("Emp_L_Name: ", lname.get_text())

当我为经理运行相同的代码时,它似乎可以工作。

manager = soup.find("manager")

【问题讨论】:

  • 既然你在处理xml,你最好使用像lxml这样的xml解析器。

标签: python arrays xml beautifulsoup attributes


【解决方案1】:

如果结构几乎相同,您可以尝试 'find_all()' given 的所有元素并检查是否只有一个或两个。

given= i.find_all('given')
fname = given[0]
print("Emp_F_Name: ", fname.get_text())
    
mname = given[1].get_text() if len(given) > 1 else None
print("Emp_M_Name: ", mname)

认为没有必要遍历employee,但如果是这样,你应该使用你的i

示例

import requests
from bs4 import BeautifulSoup

xml='''<?xml version="1.0" encoding="utf-8"?>
    <org value="Tech">
    <employee>
    <name>
    <family>Jones</family>
    <given>Jill</given>
    </name>
    </employee>
    <manager>
    <name>
    <family>Fisher</family>
    <given>Junior</given>
    <given>H</given>
    </name>
    </manager>
    </org>'''

soup = BeautifulSoup(xml, 'lxml')

employee = soup.find("employee")

for i in employee.find_all('name'):
    given= i.find_all('given')
    fname = given[0]
    print("Emp_F_Name: ", fname.get_text())
    
    mname = given[1].get_text() if len(given) > 1 else None
    print("Emp_M_Name: ", mname)
    
    lname = i.find('family')
    print("Emp_L_Name: ", lname.get_text())

输出

Emp_F_Name:  Jill
Emp_M_Name:  None
Emp_L_Name:  Jones

替代方案

employee 隔离为分离树以与find_next() 一起操作:

employee = BeautifulSoup(str(soup.find("employee")), 'lxml')

for i in employee.find_all('name'):
    fname = i.find('given')
    print("Emp_F_Name: ", fname.get_text())
    
    mname = fname.find_next('given').get_text() if fname.find_next('given') else None
    print("Emp_M_Name: ", mname)
    
    lname = i.find('family')
    print("Emp_L_Name: ", lname.get_text())

【讨论】:

  • 两种情况都有效!这非常有帮助。谢谢!
【解决方案2】:

使用 XML 解析器:(不需要任何外部库)

import xml.etree.ElementTree as ET


xml = '''<?xml version="1.0" encoding="UTF-8"?>
<org value="Tech">
   <employee>
      <name>
         <family>Jones</family>
         <given>Jill</given>
      </name>
   </employee>
   <manager>
      <name>
         <family>Fisher</family>
         <given>Junior</given>
         <given>H</given>
      </name>
   </manager>
</org>'''



attrs = {'Emp_F_Name':'given',
         'Emp_L_Name':'family',
         'Emp_M_Name': None}

root = ET.fromstring(xml)
name = root.find('.//name')
for k,v in attrs.items():
  print(f'{k}: {name.find(v).text if v else None}')

输出

Emp_F_Name: Jill
Emp_L_Name: Jones
Emp_M_Name: None

【讨论】:

  • 这太棒了。感谢 elementTree 示例!
  • @Jaytee 很高兴我能帮上忙。请接受答案。
猜你喜欢
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多