【问题标题】:Beautifulsoup HTML data extraction with BeautifulSoup and PythonBeautifulsoup 使用 BeautifulSoup 和 Python 提取 HTML 数据
【发布时间】:2013-01-29 15:42:13
【问题描述】:

我的 HTML 文本看起来像以下结构的许多实例:

<DOC>
<DOCNO> XXX-2222 </DOCNO>
<FILEID>AP-NR-02-12-88 2344EST</FILEID>
<HEAD>Reports Former Saigon Officials Released from Re-education Camp</HEAD>
<TEXT>
Lots of text here
</TEXT>
</DOC>

我需要做的是索引每个结构,包括 DocNo、标题和文本,以便稍后进行分析(标记化等)。

我正在考虑使用 BeautifulSoup,这是我目前拥有的代码:

soup = BeautifulSoup (file("AP880212.html").read()) 
num = soup.findAll('docno')

但这只会给我以下格式的结果:

<docno> AP880212-0166 </docno>, <docno> AP880212-0167 </docno>, <docno> AP880212-0168 </docno>, <docno> AP880212-0169 </docno>, <docno> AP880212-0170 </docno>

如何提取 中的数字?并将它们与标题和文本链接?

非常感谢,

萨沙

【问题讨论】:

    标签: python html xml xml-parsing beautifulsoup


    【解决方案1】:

    要获取标签的内容:

    docnos = soup.findAll('docno')
    for docno in docnos:
        print docno.contents[0]
    

    【讨论】:

    • 如果我想链接文档编号、标题和文档?
    • 您可以遍历soup.findAll('doc'),在遍历soup.findAll('docno') 之前收集您想要的标签内容,并在第一个循环中创建键并在第二个循环中建立值。也就是说,有一个嵌套循环(不是附加循环)。
    • 还可以考虑使用BeautifulStoneSoup,因为这是xml。它易于使用(就像 BeautifulSoup 一样)。执行from BeautifulSoup import BeautifulStoneSoup 并像平常一样使用它
    • @That1Guy BeautifulStoneSoupbs4 中已弃用。我承认它也是我第一次尝试的:)。它已被替换为将 features="xml" kwarg 传递给 BeautifulSoup 构造函数。
    • @PreetKukreti 绝对正确。我的印象是 OP 正在使用 BeautifulSoup 3(findAllfind_all 在他们的代码中)。谢谢你的纠正。我个人使用 3,因为我发现 bs4 有点错误。
    【解决方案2】:

    类似这样的:

    html = """<DOC>
    <DOCNO> XXX-2222 </DOCNO>
    <FILEID>AP-NR-02-12-88 2344EST</FILEID>
    <HEAD>Reports Former Saigon Officials Released from Re-education Camp</HEAD>
    <TEXT>
    Lots of text here
    </TEXT>
    </DOC>
    """
    
    import bs4
    
    d = {}
    
    soup = bs4.BeautifulSoup(html, features="xml")
    docs = soup.findAll("DOC")
    for doc in docs:
        d[doc.DOCNO.getText()] = (doc.HEAD.getText(), doc.TEXT.getText())
    
    print d
    #{u' XXX-2222 ': 
    #   (u'Reports Former Saigon Officials Released from Re-education Camp', 
    #    u'\nLots of text here\n')}
    

    请注意,我将features="xml" 传递给构造函数。这是因为您的输入中有很多非标准的 html 标签。在将文本保存到字典之前,您可能还需要 .strip() 文本,因此它对空格不那么敏感(当然,除非这是您的意图)。

    更新:

    如果同一文件中有多个 DOC,而 features="xml" 限制为一个,可能是因为 XML 解析器预计只有一个根元素。

    例如如果将整个输入 XML 包装在单个根元素中,它应该可以工作:

    <XMLROOT>
        <!-- Existing XML (e.g. list of DOC elements) -->
    </XMLROOT>
    

    所以您可以在文件中执行此操作,或者我建议在将输入文本传递给 beautifulsoup 之前以编程方式执行此操作:

    root_element_name = "XMLROOT"  # this can be anything
    rooted_html = "<{0}>\n{1}\n</{0}>".format(root_element_name, html)
    soup = bs4.BeautifulSoup(rooted_html, features="xml")
    

    【讨论】:

    • 如果我想从目录中读出一系列 .html 文件?目前我正在为 glob.glob(os.path.join(path,'*.html')) 中的 infile 执行 path = '/TREC-AP88-90-qrels1-50/Docs':soup = BeautifulSoup (file( infile).read(), features="xml") 然后是你的代码,但它没有给我正确的结果..
    • 事实上,是 'xml' 部分使它在第一个文档之后停止.. 有什么办法可以解决这个问题吗?
    • @user2070177 查看我的更新。我已经使用多个文档对其进行了测试,并且可以正常工作。
    • @user2070177 您可以将此代码包装在一个函数中,该函数采用原始 html 文本并返回一个字典;返回字典,然后您可以使用dict.update(..) 将其聚合到主字典(在主目录/文件迭代循环的范围内)。这是一个更干净、更好的分离设计。
    【解决方案3】:
    docnos = soup.findAll('docno')
    for docno in docnos:
           print docno.renderContents()
    

    您也可以使用renderContents()从标签中提取信息。

    【讨论】:

      猜你喜欢
      • 2020-06-03
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多