【问题标题】:BeautifulSoup find the next specific tag following a found tagBeautifulSoup 在找到的标签之后查找下一个特定标签
【发布时间】:2016-01-27 23:55:09
【问题描述】:

鉴于以下内容(从较大的文档中简化)

<tr class="row-class">
  <td>Age</td>
  <td>16</td>
</tr>
<tr class="row-class">
  <td>Height</td>
  <td>5.6</td>
</tr>
<tr class="row-class">
  <td>Weight</td>
  <td>103.4</td>
</tr>

我尝试使用bs4lxml 从相应的行返回16。问题似乎是两个td标签之间有一个Navigable String,所以

page.find_all("tr", {"class":"row-class"})

使用

生成结果集
result[0] = {Tag} <tr class="row-class"> <td>Age</td> <td>16</td> </tr>
result[1] = {Tag} <tr class="row-class"> <td>Height</td> <td>5.6</td> </tr>
result[2] = {Tag} <tr class="row-class"> <td>Weight</td> <td>103.4</td> </tr>

这很好,但我无法获得第二个td 中的字符串。每一行的内容类似于

[' ', <td>Age</td>, ' ', <td>16</td>, ' ']

tdtag' 'Navigable String。这种差异使我无法使用next_elementnext_sibling 便捷方法访问正确的文本,例如:

如果我使用:

find("td", text=re.compile(r'Age')).get_text()

我收到Age。但是如果我尝试通过

访问下一个元素
find("td", text=re.compile(r'Age')).next_element()

我明白了

'NavigableString' 对象不可调用

由于在result 中包裹了NavigableStrings,所以用previous_element 向后移动也有同样的问题。

我如何从找到的Tag 移动到下一个Tag,跳过两者之间的next_element?有没有办法从result 中删除这些' '

我应该指出,我已经尝试过以如下方式务实:

    for r in (sp.find_all("tr", {"class":"row-class"})):
        age = r.find("td", text=re.compile(r"\d\d")).get_text()

它可以工作...直到我解析一个文档,该文档在Age 之前具有匹配的\d\d 的另一个订单。

我也知道我可以

find("td", text=re.compile(r'Age')).next_sibling.next_sibling

但这是硬烤结构。

所以我需要在搜索中具体找到具有目标字符串的td,然后在下一个td中找到值。我知道我可以构建一些逻辑来测试每一行,但似乎我遗漏了一些明显且更优雅的东西......

【问题讨论】:

    标签: python parsing beautifulsoup


    【解决方案1】:

    如果您获取元素列表,则可以使用[index] 从列表中获取元素。

    data = """<tr class="row-class">
      <td>Age</td>
      <td>16</td>
    </tr>
    <tr class="row-class">
      <td>Height</td>
      <td>5.6</td>
    </tr>
    <tr class="row-class">
      <td>Weight</td>
      <td>103.4</td>
    </tr>"""
    
    from bs4 import BeautifulSoup
    
    soup = BeautifulSoup(data)
    
    trs = soup.find_all("tr", {"class":"row-class"})
    
    for tr in trs:
        tds = tr.find_all("td") # you get list
    
        print('text:', tds[0].get_text()) # get element [0] from list
        print('value:', tds[1].get_text()) # get element [1] from list
    

    结果

    text: Age
    value: 16
    text: Height
    value: 5.6
    text: Weight
    value: 103.4
    

    【讨论】:

    • 谢谢。我知道我可以做到这一点(以前做过很多次)。如果您查看我帖子中的for 循环,您基本上会看到您所要求的内容。这就是我在写I know I could build some logic that tests each row 时的意思,但在这里我正在寻找在 bs4 中的便利方法中找到受支持的方法或类似的方法,这将让我跳到下一个 tag 兄弟姐妹或其他类似的优雅方法!跨度>
    猜你喜欢
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 2020-10-05
    • 2018-10-11
    • 2023-04-04
    • 1970-01-01
    • 2012-11-04
    相关资源
    最近更新 更多