【问题标题】:BeautifulSoup - find_all div tags with different class nameBeautifulSoup - find_all 具有不同类名的 div 标签
【发布时间】:2018-07-30 07:27:11
【问题描述】:

我想选择所有<div>,其中类名是post has-profile bg2post has-profile bg1,但不是最后一个,即panel

<div id="6" class="post has-profile bg2"> some text 1 </div>
<div id="7" class="post has-profile bg1"> some text 2 </div>
<div id="8" class="post has-profile bg2"> some text 3 </div>
<div id="9" class="post has-profile bg1"> some text 4 </div>

<div class="panel bg1" id="abc"> ... </div>

select() 仅匹配单个匹配项。我正在尝试使用find_all(),但是 bs4 无法找到它。

if soup.find(class_ = re.compile(r"post has-profile [bg1|bg2]")):
    posts = soup.find_all(class_ = re.compile(r"post has-profile [bg1|bg2]"))

如何使用正则表达式和不使用正则表达式来解决它?谢谢。

【问题讨论】:

    标签: python-3.x beautifulsoup


    【解决方案1】:

    您可以在 BeautifulSoup 中使用内置的 CSS 选择器:

    data = """<div id="6" class="post has-profile bg2"> some text 1 </div>
    <div id="7" class="post has-profile bg1"> some text 2 </div>
    <div id="8" class="post has-profile bg2"> some text 3 </div>
    <div id="9" class="post has-profile bg1"> some text 4 </div>
    <div class="panel bg1" id="abc"> ... </div>"""
    
    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(data, 'lxml')
    
    divs = soup.select('div.post.has-profile.bg2, div.post.has-profile.bg1')
    
    for div in divs:
        print(div)
        print('-' * 80)
    

    打印:

    <div class="post has-profile bg2" id="6"> some text 1 </div>
    --------------------------------------------------------------------------------
    <div class="post has-profile bg2" id="8"> some text 3 </div>
    --------------------------------------------------------------------------------
    <div class="post has-profile bg1" id="7"> some text 2 </div>
    --------------------------------------------------------------------------------
    <div class="post has-profile bg1" id="9"> some text 4 </div>
    --------------------------------------------------------------------------------
    

    'div.post.has-profile.bg2, div.post.has-profile.bg1' 选择器选择类为 "post hast-profile bg2" 的所有 &lt;div&gt; 标记和类为 "post hast-profile bg1" 的所有 &lt;div&gt; 标记。

    【讨论】:

    • 以美丽的汤的方式,这是一个完美的答案。我不知道 select() 可以接受这样的多个参数。
    • @pss 你的正则表达式似乎没问题,我会尝试删除方括号并加上括号 - (bg1|bg2)。但取决于您通过 BeautifulSoup 解析的输入。只有当它们的类按指定顺序排列时,您的正则表达式才会匹配所有 div。
    【解决方案2】:

    您可以定义一个描述感兴趣标签的函数:

    def test_tag(tag):
        return tag.name=='div' \
           and tag.has_attr('class') \
           and "post" in tag['class'] \
           and "has-profile" in tag['class'] \
           and ("bg1" in tag['class'] or "bg2" in tag['class']) \
           and "panel" not in tag['class']
    

    并将函数应用于“汤”:

    soup.findAll(test_tag)
    

    【讨论】:

      【解决方案3】:

      使用正则表达式。

      试试:

      from bs4 import BeautifulSoup
      import re
      s = """<div id="6" class="post has-profile bg2"> some text 1 </div>
      <div id="7" class="post has-profile bg1"> some text 2 </div>
      <div id="8" class="post has-profile bg2"> some text 3 </div>
      <div id="9" class="post has-profile bg1"> some text 4 </div>
      
      <div class="panel bg1" id="abc"> ... </div>"""
      
      soup = BeautifulSoup(s, "html.parser")
      for i in soup.find_all("div", class_=re.compile(r"post has-profile bg(1|2)")):
          print(i)
      

      输出:

      <div class="post has-profile bg2" id="6"> some text 1 </div>
      <div class="post has-profile bg1" id="7"> some text 2 </div>
      <div class="post has-profile bg2" id="8"> some text 3 </div>
      <div class="post has-profile bg1" id="9"> some text 4 </div>
      

      【讨论】:

      • 我按原样尝试了您的代码,但输出中没有任何内容,即空白输出。
      • 你是如何获得原始 html 的?使用requests.get?
      • 原始 html 在数据库中。我将原始 html 分配给一个变量 - content = mydocDict['content'] soup = BeautifulSoup(content, 'html.parser')
      猜你喜欢
      • 2023-04-08
      • 1970-01-01
      • 2023-01-04
      • 2017-03-13
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 2016-02-12
      • 1970-01-01
      相关资源
      最近更新 更多