BeautifulSoup在找到的标签后面找到下一个特定标签

时间:2016-01-27 23:55:10

标签: python parsing beautifulsoup

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

<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>

我尝试使用16bs4从相应的行返回lxml。问题似乎是两个Navigable String标记之间存在td,因此

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()

我得到了

  

&#39; NavigableString&#39;对象不可调用

由于NavigableStrings中包裹result,因此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()

它有效...直到我在\d\d之前解析具有匹配Age的另一个订单的文档。

我也知道,我可以

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

但这对结构来说是难以烘焙的。

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

1 个答案:

答案 0 :(得分:3)

如果您获得了元素列表,那么您可以使用[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