【问题标题】:Creating Pandas dataframe from nested unordered html lists从嵌套的无序 html 列表创建 Pandas 数据框
【发布时间】:2018-05-07 18:23:57
【问题描述】:

我有一个无序列表网页,我想将它们转换为 pandas 数据框,作为 NLP 工作流程的第一步。

import pandas as pd
from bs4 import BeautifulSoup
html = '''<html>
        <body>
          <ul>
              <li>
              Name
                    <ul>
                        <li>Many</li>
                        <li>Stories</li>
                    </ul>
                </li> 
          </ul>
          <ul>
              <li>
              More
              </li>
         </ul>
         <ul>
             <li>Stuff 
                     <ul>
                         <li>About</li>
                    </ul>
            </li>
        </ul>
        </body>
        </html>'''

 soup = BeautifulSoup(html, 'lxml')

目标是让每个顶级列表变成一个数据框,看起来像这样的输出:

   0    1     2
0 Name  Many  Stories
1 More  null  null
2 Stuff About null

我尝试使用以下代码获取所有列表项(包含子列表)

target = soup.find_all('ul')

但它返回双输出:

[<li>
                   Name
                         <ul>
 <li>Many</li>
 <li>Stories</li>
 </ul>
 </li>, <li>Many</li>, <li>Stories</li>, <li>
                   More
                   </li>, <li>Stuff 
                          <ul>
 <li>About</li>
 </ul>
 </li>, <li>About</li>]

真的迷路了。谢谢。

【问题讨论】:

  • 首先,您要查找页面上的所有ul 元素,因此因为“Many”和“Stories”包含在两个不同的ul 元素下,您会看到它们两次.通过使用特定路径而不是一揽子搜索所有内容,可能会更好地指定您想要的 ul 元素
  • 为了补充上面关于路径的观点,您似乎正在寻找出现在body 标记之后的ul 元素,因此请定义该路径。重复的实例是由于body &gt; ul &gt; li &gt; ul 造成的,soup.find_all('ul') 也是如此
  • 我建议您查看here,以便您可以使用 XPaths 来帮助您解决此问题。您的 XPath 最终会是这样的:body/ul。单斜杠表示任何ul 元素,它是body 元素的直接子元素
  • 感谢@WStokvis,我可以使用 xpath 获取每个列表的顶层,但无法弄清楚如何迭代每个列表。我有成千上万的这些要排序,而且都是 1990 年代未标记的 html。
  • 如果没有更多内容可供使用,我无法提供有关如何正确编码以便获得所需内容的见解。我想我首先要看的是您是否可以编写一些逻辑来搜索树中嵌套的ul 元素。例如,如果您看到 &lt;ul&gt; 跟随另一个 &lt;ul&gt; 而没有 &lt;/ul&gt;,那么显然这些元素将被嵌套,因此您需要区别对待它们。

标签: python pandas xpath nlp elementtree


【解决方案1】:

在 cmets 中崩溃,尽情享受吧!

from lxml import etree
import re

#Convert html string to correct format for parsing with XPATHs
root = etree.XML(html)
tree = etree.ElementTree(root)

#Your XPATH Selector 
xpathselector = 'body/ul'

#List of lxml items that need to be decoded
hold = tree.xpath(xpathselector)

'''
1. Get strings of each item in hold
2. Decode to string
3. Remove all tags and \n in each list
4. Split on spaces to create list of lists
'''
df = pd.DataFrame([re.sub('(\\n)|(\<.{0,3}\>)','',etree.tostring(i).decode('utf-8')).split() for i in hold])
df
       0      1        2
0   Name   Many  Stories
1   More   None     None
2  Stuff  About     None

【讨论】:

    猜你喜欢
    • 2021-04-20
    • 2022-08-03
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 2023-03-23
    • 2018-06-01
    相关资源
    最近更新 更多