【问题标题】:Parsing XML with Beautiful Soup用 Beautiful Soup 解析 XML
【发布时间】:2023-03-24 16:29:01
【问题描述】:

编辑:已解决。以为我会在底部添加我的答案...

注意:所需的输出是一堆类似

的行
US D0591026

我的 XML 数据如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE us-patent-grant SYSTEM "us-patent-grant-v42-2006-08-23.dtd" [ ]>
<us-patent-grant lang="EN" dtd-version="v4.2 2006-08-23" file="USD0591026-20090428.XML" status="PRODUCTION" id="us-patent-grant" country="US" date-produced="20090414" date-publ="20090428">
<us-bibliographic-data-grant>
<publication-reference>
<document-id>
<country>US</country>
<doc-number>D0591026</doc-number>
<kind>S1</kind>
<date>20090428</date>
</document-id>
</publication-reference>
<application-reference appl-type="design">
<document-id>
<country>US</country>
<doc-number>29303426</doc-number>
<date>20080208</date>
</document-id>
</application-reference>
<us-application-series-code>29</us-application-series-code>
<priority-claims>
<priority-claim sequence="01" kind="national">
<country>CA</country>
<doc-number>122078</doc-number>
<date>20070830</date>
</priority-claim>
</priority-claims>
<us-term-of-grant>
<length-of-grant>14</length-of-grant>
</us-term-of-grant>
<classification-locarno>
<edition>9</edition>
<main-classification>0101</main-classification>
</classification-locarno>
<classification-national>
<country>US</country>
<main-classification>D 1106</main-classification>
</classification-national>
<invention-title id="d0e71">Edible fruit product in the shape of a rocketship</invention-title>
<references-cited>

我正在尝试提取国家,以及文件编号。我已经到了这一点:

import os
import io
from bs4 import BeautifulSoup
import csv
import requests

directory_in_str = 'C:/Users/somedirectory'
directory = os.fsencode(directory_in_str)

for file in os.listdir(directory):
    filename = os.fsdecode(file)
    full_name = directory_in_str + filename
    handler = open(full_name).read()
    soup = BeautifulSoup(handler, 'lxml')
    patents=soup.find_all('us-patent-grant')
    pub_ref=soup.find_all('publication-reference')
    country=soup.find_all('country')
    doc_num=soup.find_all('doc-number')
    for patent in pub_ref:
        for doc_num in patent:
            print(doc_num)

    continue

我可以在哪里打印出一个包含这些元素的好块(上面的代码所做的),但是我试图获取这两个特定元素(然后连接它们)的一切都失败了。我已经能够使用字符串操作来做到这一点,但是数据集的格式不够好(稍后我将提取没有标准长度的文本字段),我确信我可以基于拼接字符串执行整个分析。

有什么想法可以深入研究这些标签并仅返回这两个元素吗?

好的,所以我做了一些更改,并将我的代码:

import os
import io
from bs4 import BeautifulSoup
import csv
import requests

directory_in_str = 'C:/somedir'

directory = os.fsencode(directory_in_str)

for file in os.listdir(directory):
    filename = os.fsdecode(file)
    full_name = directory_in_str + filename
    handler = open(full_name).read()
    soup = BeautifulSoup(handler, 'lxml')
    patents=soup.find_all('us-patent-grant')
    pub_ref=soup.find_all('publication-reference')
    for patent in pub_ref:
     country = patent.find_all('country')
     doc_num = patent.find_all('doc-number')
     print(country + doc_num)

    continue

这给了我大部分我想要的东西。我得到了这个:

[<country>US</country>, <doc-number>D0591026</doc-number>]

但我想要的只是:

US D0591026

我知道对象的类型是 bs4 结果集,但我对如何只返回标签中的内容还不够熟悉。最终,这将是一个 csv,所以我不想在那里有这些标签。

我将汤对象转换为字符串并使用正则表达式来获得所需的输出

...
import re
...
...
     country = patent.find_all('country')
     doc_num = patent.find_all('doc-number')
     country_str = str(country)
     doc_num_str = str(doc_num)
     country_str2 = re.search('>(.*)<', country_str)
     doc_num_str2 = re.search('>(.*)<', doc_num_str)
     print(country_str2.group(1) + doc_num_str2.group(1))

【问题讨论】:

  • 您是否查看过 XPath 或改用 etree 模块?根据我的经验,Beautfulsoup 主要用于 HTML
  • 我不明白您想要的输出,它是一个列表,哪些元素是带有文档编号的列表及其相关国家/地区?
  • Edit 你的问题并显示你想要的输出。
  • 谢谢,cricket_007,我试过 etree,但我得到的只是这个错误:xml.etree.ElementTree.ParseError: undefined entity ©: line 56, column 106. 如果我了解 etree 的文档对,这意味着xml是非标准的,所以我必须添加每个不合格的元素/标签?
  • @JohnDoe 我认为您使用re 的解决方案过于矫枉过正,您可以使用.text 在bs4 中选择标签内的文本,正如我和吉普赛人在我们的回答中所建议的那样。我很高兴您解决了您的问题,但编辑问题以包含您的答案违反了 SO 准则,您应该将您的答案发布为您自己问题的答案,然后 accept 最有帮助的答案,这是一个总体上对社区有利。

标签: python xml beautifulsoup


【解决方案1】:

试试这个:

doc_nums=soup.find_all('doc-number')
for num in doc_nums:
  print(num.text)

【讨论】:

    【解决方案2】:

    要使用列表理解和zip 获得一个带有doc-number 的列表并且它与country 相关,一个简单的单行将是:

    >>> [(country.text,number.text) for country, number in zip(soup.findAll("country"), soup.findAll("doc-number"))]
    [('US', 'D0591026'), ('US', '29303426'), ('CA', '122078')]
    

    如果您不习惯列出推导式,也许是一种更易读的方式:

    >>> lst = []
    >>> for country, number in zip(soup.findAll("country"), soup.findAll("doc-number")):
        print(country.text, number.text)
        lst.append((country.text, number.text))
    
    
    US D0591026
    US 29303426
    CA 122078
    >>> lst
    [('US', 'D0591026'), ('US', '29303426'), ('CA', '122078')]
    

    【讨论】:

      猜你喜欢
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 2018-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-03
      • 2015-11-08
      相关资源
      最近更新 更多