2013-11-25 40 views
2

我有一个关于使用其子项属性之一的条件来选择标签列表(或单个标签)的问题。具体地,给出的HTML代码:根据美丽的汤中儿童的文本值查找标签列表

<tbody> 
<tr class="" data-row="0"> 
<tr class="" data-row="1"> 
<tr class="" data-row="2"> 
    <td align="right" csk="13">13</td> 
    <td align="left" csk="Jones,Andre"><a href="/players/andre-jones-2.html">Andre Jones</a>  
    </td> 
<tr class="" data-row="3"> 
    <td align="right" csk="7">7</td> 
    <td align="left" csk="Jones,DeAndre"><a href="/players/deandre-jones-1.html">DeAndre Jones</a> 
    </td> 
<tr class="" data-row="4"> 
<tr class="" data-row="5"> 

我有一个Unicode变量从外部环路来了,我想通过每行看在表Player==Table.tr.a.text提取<tr>标签和识别重复的球员名字Table。因此,举例来说,如果有多于一名玩家Player=Andre Jones,MyRow对象返回包含该玩家名称的所有<tr>标签,而如果只有一行Player=Andre Jones,那么MyRow仅包含具有等于锚文本属性的单个元素<tr>Andre Jones。我一直在努力的事情像

Table = soup.find('tbody') 
MyRow = Table.find_all(lambda X: X.name=='tr' and Player == X.text) 

但这返回[]MyRow。如果我使用

MyRow = Table.find_all(lambda X: X.name=='tr' and Player in X.text) 

这将挑选具有PlayerX.text一个子任何<tr>。在上面的示例代码中,它提取了<tr>标签与Table.tr.td.a.text=='Andre Jones'Table.tr.td.a.text=='DeAndre Jones'。任何帮助,将不胜感激。

回答

0

无论你的愿望。 :)

解决方法1

逻辑:找到的第一个标签,其标签名称为TR,并包含“FooName”在这个标签中的文本,包括它的孩子。

# Exact Match (text is unicode, turn into str) 
print Table.find(lambda tag: tag.name=='tr' and 'FooName' == tag.text.encode('utf-8')) 
# Fuzzy Match 
# print Table.find(lambda tag: tag.name=='tr' and 'FooName' in tag.text) 

输出:

<tr class="" data-row="2"> 
<td align="right" csk="3">3</td> 
<td align="left" csk="Wentz,Parker"> 
<a href="/players/Foo-Name-1.html">FooName</a> 
</td> 
</tr> 

溶液2

逻辑:找到其文本包含FooName元素,在这种情况下anchor标签。然后去了树,并搜索其所有家长(包括祖先),它的标记名称是tr

# Exact Match 
print Table.find(text='FooName').find_parent('tr') 
# Fuzzy Match 
# import re 
# print Table.find(text=re.compile('FooName')).find_parent('tr') 

输出

<tr class="" data-row="2"> 
<td align="right" csk="3">3</td> 
<td align="left" csk="Wentz,Parker"> 
<a href="/players/Foo-Name-1.html">FooName</a> 
</td> 
</tr> 
+0

太好了!非常感谢你的帮助。 –

+0

@MarkClements请标记最能帮助您的答案,以便其他人可以轻松搜索。 –

+0

代码似乎是匹配首字母或姓氏,而不是整个名称。因此,它不仅将“安德烈琼斯”和“德安德鲁琼斯”视为相同,还包括“特伦斯”和“特伦斯萨尔斯伯里”。 –

2

您可以用XPath和LXML做到这一点很容易:

import lxml.html 

root = lxml.html.fromstring('''...''') 
td = root.xpath('//tr[.//a[text() = "FooName"]]') 

BeautifulSoup“等效”将类似于:

rows = soup.find('tbody').find_all('tr') 
td = next(row for row in rows if row.find('a', text='FooName')) 

或者,如果你向后想一想:

td = soup.find('a', text='FooName').find_parent('tr') 
+0

我还没有学过lxml,但是感谢BS解决方案。 –

+0

你提供的美丽的汤码只会给我第一次出现'text ='FooName''。我已经完善了我的问题,以更具体地了解我在找什么。谢谢你的帮助。 –

+0

@MarkClements:那么XPath表达式就可以工作了。 – Blender