【问题标题】:Extracting HTML between tags在标签之间提取 HTML
【发布时间】:2016-11-12 10:26:47
【问题描述】:

我想提取特定 HTML 标记之间的所有 HTML。

<html>
<div class="class1">Included Text</div>
[...]
<h1><b>text</b></h1><span>[..]</span><div>[...]</div>
[...]
<span class="class2">
[...]</span>

所以想在 class1 divclass2 span 之间查找所有 HTML(标签和值)。

Included Text
<h1><b>text</b></h1><span>[..]</span><div>[...]</div>

HTML 文件中也有多次出现,所以我想将它们全部匹配。这就是我的意思:

<html>
(first occurrence)
<div class="class1">Included Text</div>
[...]
<h1><b>text</b></h1><span>[..]</span><div>[...]</div>
[...]
<span class="class2">
[...]</span>

(2nd occurrence)
<div class="class1">Included Text</div>
[...]
<h1><b>text</b></h1><span>[..]</span><div>[...]</div>
[...]
<span class="class2">
[...]</span>  

(third occurrence)
<div class="class1">Included Text</div>
[...]
<h1><b>text</b></h1><span>[..]</span><div>[...]</div>
[...]
<span class="class2">
[...]</span>  
</html>

我一直在使用 Beautifulsoup 4 寻找答案。但是,所有问题/答案都与提取文本之间的值有关,但这不是我想要的。我还想知道 Beautifulsoup 是否可以做到这一点,或者我是否必须改用正则表达式。

【问题讨论】:

    标签: python beautifulsoup


    【解决方案1】:

    您可以使用 bs4itertools.takewhile

    来扮演自己的角色
    h  = """<html>
     <div class="class1">Included Text</div>
    [...]
    <h1><b>text</b></h1><span>[..]</span><div>[...]</div>
    [...]
    <span class="class2">
    [...]</span>"""
    
    soup = BeautifulSoup(h)
    def get_html_between(start_select, end_tag, cls):
        start = soup.select_one(start_select)
        all_next = start.find_all_next()
        yield "".join(start.contents)
        for t in takewhile(lambda tag: tag.get("name") != end_tag and tag.get("class") != [cls], all_next):
            yield t
    
    for ele in get_html_between("div.class1","div","class2"):
        print(ele)
    

    输出:

    Included Text
    <h1><b>text</b></h1>
    <b>text</b>
    <span>[..]
    </span>
    <div>[...]</div>
    

    为了让它更灵活一点,你可以传入初始标签和一个 cond lambda/function,对于多个 class1 只需迭代并传递每个:

    def get_html_between(start_tag, cond):
        yield "".join(start_tag.contents)
        all_next = start_tag.find_all_next()
        for ele in takewhile(cond, all_next):
            yield ele
    
    
    cond = lambda tag: tag.get("name") != "div" and tag.get("class") != ["class2"]
    soup = BeautifulSoup(h, "lxml")
    for tag in soup.select("div.class1"):
        for ele in get_html_between(tag, cond):
            print(ele)
    

    使用您最新的编辑:

    In [15]: cond = lambda tag: tag.get("name") != "div" and tag.get("class") != ["class2"]
    
    In [16]: for tag in soup.select("div.class1"):            
                for ele in get_html_between(tag, cond):
                    print(ele)
                print("\n")
       ....:         
    Included Text
    <h1><b>text</b></h1>
    <b>text</b>
    <span>[..]</span>
    <div>[...]</div>
    
    
    Included Text
    <h1><b>text</b></h1>
    <b>text</b>
    <span>[..]</span>
    <div>[...]</div>
    
    
    Included Text
    <h1><b>text</b></h1>
    <b>text</b>
    <span>[..]</span>
    <div>[...]</div>
    

    【讨论】:

    • 感谢您的帮助。我变得更接近了,但我不清楚我最终想要实现什么,我的错。我现在想要的只是在第一个 div 标签中包含文本。此外,HTML 文件中的两个标签之间也多次出现 HTML。我想迭代它们并将它们全部 grep。
    • 谢谢帕德莱克,我想我们快到了我已经编辑了我的问题以澄清我的意思是“匹配”多次出现。
    • @user3030473,最后一个代码块似乎完全符合你的要求,它怎么不适合你?
    • 非常感谢。输出由多个带有元素的列表组成。我希望输出是单个字符串。我通过使用 UTF-8 编码写入文件来解决这个问题,然后重新打开文件,将其解码为值中的一个字符串。
    猜你喜欢
    • 2016-09-10
    • 2013-05-23
    • 2015-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多