【问题标题】:getchildren() in Beautifulsoup code to LXMLBeautifulsoup 代码中的 getchildren() 到 LXML
【发布时间】:2018-11-07 07:09:35
【问题描述】:

我必须转换一些 beautifulsoup 代码。 基本上我想要的只是获取正文节点的所有子节点并选择具有文本并存储它们。 这是 bs4 的代码:

def get_children(self, tag, dorecursive=False):

    children = []
    if not tag :
        return children

    for t in tag.findChildren(recursive=dorecursive):
        if t.name in self.text_containers \
                and len(t.text) > self.min_text_length \
                and self.is_valid_tag(t):
            children.append(t)
    return children

这很好用 当我用 lxml lib 尝试这个时,孩子是空的:

def get_children(self, tag, dorecursive=False):

    children = []
    if not tag :
        return children

    tags = tag.getchildren()
    for t in tags:
        #print(t.tag)
        if t.tag in self.text_containers \
                and len(t.tail) > self.min_text_length \
                and self.is_valid_tag(t):
            children.append(t)
    return children

有什么想法吗?

【问题讨论】:

    标签: beautifulsoup lxml


    【解决方案1】:

    代码:

    import lxml.html
    import requests
    
    
    class TextTagManager:
        TEXT_CONTAINERS = {
            'li',
            'p',
            'span',
            *[f'h{i}' for i in range(1, 6)]
        }
        MIN_TEXT_LENGTH = 60
    
        def is_valid_tag(self, tag):
            # put some logic here
            return True
    
        def get_children(self, tag, recursive=False):
            children = []
    
            tags = tag.findall('.//*' if recursive else '*')
            for t in tags:
                if (t.tag in self.TEXT_CONTAINERS and
                        t.text and
                        len(t.text) > self.MIN_TEXT_LENGTH and
                        self.is_valid_tag(t)):
                    children.append(t)
            return children
    
    
    manager = TextTagManager()
    
    url = 'https://en.wikipedia.org/wiki/Comparison_of_HTML_parsers'
    html = requests.get(url).text
    doc = lxml.html.fromstring(html)
    
    for child in manager.get_children(doc, recursive=True):
        print(child.tag, ' -> ', child.text)
    

    输出:

    li  ->  HTML traversal: offer an interface for programmers to easily access and modify of the "HTML string code". Canonical example: 
    li  ->  HTML clean: to fix invalid HTML and to improve the layout and indent style of the resulting markup. Canonical example: 
    

    .getchildren() 返回所有 直接 子级。如果你想有一个递归选项,你可以使用.findall()

    tags = tag.findall('.//*' if recursive else '*')
    

    This answer 应该可以帮助您了解.//tagtag 之间的区别。

    【讨论】:

    • 感谢您的回复。我刚刚尝试使用此网址:en.wikipedia.org/wiki/Comparison_of_HTML_parsers,但它不起作用。在您的示例中,请使用 tree.find('body') 作为起点(不是您的 div)
    • @DanyM 是的,我忘记了您还希望可以选择递归搜索。我更新了我的答案(:
    • 其实我不想递归,所以默认设置为false。我想要做的是在一些容器'p','div','article'......(不是导航,页眉,页脚......)中提取内容文本。我使用我提供的 URL(维基百科)尝试了您的示例,但没有结果。我在没有递归模式的情况下得到 5 个节点,或者在递归模式下得到 +365 个节点。我错过了一些我认为的东西
    • @DanyM 可能是的,我不知道你为什么要查看len(t.tail)?你确定你不是要检查len(t.text) 吗?让我知道它是如何工作的。
    • 谢谢,如果我单独测试它,我的代码可以工作,但集成到我的代码中,它不能按预期工作。我的所有“文本”属性都为空,所以它不解析任何东西......必须调查
    猜你喜欢
    • 1970-01-01
    • 2012-07-03
    • 2012-10-09
    • 2018-03-03
    • 1970-01-01
    • 2013-10-02
    • 2016-07-27
    • 2014-02-14
    • 2023-03-24
    相关资源
    最近更新 更多