示例html('x.html'in python snippet):
<table>
<tr>
<td>a</td>
<td>b</td>
<table><tr><td>c</td></tr></table>
</tr>
</table>
我想从表中的一行中获取一个带有三个列的列表:
[
'<td>a</td>',
'<td>b</td>',
'<table><tr><td>c</td></tr></table>'
]
我尝试简单地通过BeautifulSoup
对象迭代,但它返回整个HTML并为空(嗯,'n'
)字符串。
In [9]: soup = BeautifulSoup(open('x.html').read(), 'html.parser')
In [10]: for a in soup:
...: print(type(a))
...:
<class 'bs4.element.Tag'>
<class 'bs4.element.NavigableString'>
我也尝试使用find_all()
方法,但它找到了我不想在结果中看到的嵌套<td>c</td>
:
In [24]: len(soup.find_all('td'))
Out[24]: 4 # <-- I need 3 things, not 4
我认为find/find_all参数 recursive
是关于嵌套元素的,但我不明白它是否有效:
Signature: soup.find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)
In [26]: len(soup.find_all('td', recursive=False))
Out[26]: 0
也许写xml.sax
解析器会更容易?
正如@danielle在评论中所建议的那样,您可以获得外部tr
的.contents
。但是,由于您正在从此文件中读取,因此您将获得许多"n"
和其他不需要的元素。您可以检查isinstance(x,Tag)
是否仅获取标签内容。
在某些情况下,HTML不正确,可能没有这样的简单解决方案。在这种情况下,您也可以将自定义功能传递给find_all
。例如。您要查找的数据也可以使用此逻辑获得 - 在文件的第一个表中找到所有td
和table
标签。当然,逻辑可以与此不同,但是您会得到这个想法。
from bs4 import BeautifulSoup
from bs4 import Tag
soup = BeautifulSoup(open('x.html').read(), 'html.parser')
#solution 1
print([x for x in soup.find('tr').contents if isinstance(x,Tag)])
#solution 2 with a custom function
first_table=soup.find('table')
def is_td_or_table(item):
if isinstance(item,Tag):
if item.name in ['td','table'] and item.find_parent("table") is first_table:
return True
print(first_table.find_all(is_td_or_table))