2012-02-12 39 views
4

我的读取与BeautifulSoup一些HTML表行这段代码:选择特定<tr>标签与BeautifulSoup

from bs4 import BeautifulSoup 
import urllib2 
import re 

page = urllib2.urlopen('www.something.bla') 
soup = BeautifulSoup(page) 
rows = soup.findAll('tr', attrs={'class': re.compile('class1.*')}) 

这是我得到的结果:

<tr class="class1 class2 class3">...</tr> 
<tr class="class1 class2 class3">...</tr> 
<tr class="class1 class5">...</tr> 
<tr class="class1_a class5_a">...</tr> 
<tr class="class1 class5">...</tr> 
<tr class="class1_a class5_a">...</tr> 
<!-- etc. --> 

然而,我'想排除(或不首先选择它们)那些具有class1 class2 class3作为属性的行。

我该怎么做?
感谢您的帮助!

+0

那么'class1_a'可以抓取而不是'class1'吗? – serk 2012-02-12 23:24:24

+0

我应该抓住所有以'class1 *'开头但没有'class2 class3'的人...... – errata 2012-02-12 23:25:58

回答

8

也许没有正则表达式更容易。这适用于BeautifulSoup 3:

from BeautifulSoup import BeautifulSoup 

page = """ 
<tr class="class1 class2 class3">1</tr> 
<tr class="class1 class2 class3">2</tr> 
<tr class="class1 class5">3</tr> 
<tr class="class1_a class5_a">4</tr> 
<tr class="class1 class5">5</tr> 
<tr class="class1_a class5_a">6</tr> 
<tr>7</tr>""" 

def cond(x): 
    if x: 
     return x.startswith("class1") and not "class2 class3" in x 
    else: 
     return False 

soup = BeautifulSoup(page) 
rows = soup.findAll('tr', {'class': cond}) 

for row in rows: 
    print row 

=>

<tr class="class1 class5">3</tr> 
<tr class="class1_a class5_a">4</tr> 
<tr class="class1 class5">5</tr> 
<tr class="class1_a class5_a">6</tr> 

随着BeautifulSoup 4,我能使其工作如下:

import re 
from bs4 import BeautifulSoup 

page = """ 
<tr class="class1 class2 class3">1</tr> 
<tr class="class1 class2 class3">2</tr> 
<tr class="class1 class5">3</tr> 
<tr class="class1_a class5_a">4</tr> 
<tr class="class1 class5">5</tr> 
<tr class="class1_a class5_a">6</tr> 
<tr>7</tr>""" 

soup = BeautifulSoup(page) 
rows = soup.find_all('tr', {'class': re.compile('class1.*')}) 

for row in rows: 
    cls = row.attrs.get("class") 
    if not ("class2" in cls or "class3" in cls): 
     print row 

=>

<tr class="class1 class5">3</tr> 
<tr class="class1_a class5_a">4</tr> 
<tr class="class1 class5">5</tr> 
<tr class="class1_a class5_a">6</tr> 

在BS4中,像class这样的多值属性具有字符串列表作为它们的值,而不是字符串。见http://www.crummy.com/software/BeautifulSoup/bs4/doc/#id12

+0

啊,是的,lambda :)看起来很优雅:)但是,我得到了一个错误:'' AttributeError:'NoneType'对象没有属性'startswith'' ...我从来没有使用过lamba函数,并试图'修复'这个错误,但实际上没有得到任何答案: -/ – errata 2012-02-14 10:16:48

+1

它没有成为拉姆达。当代码没有'class'属性和x ='None'时,代码更新以处理案例(例如,在我的示例中为''7)。 – mzjn 2012-02-14 16:29:04

+0

感谢您对此的帮助,但无论您尝试使用哪一个示例,我在控制台中始终获得与您的不同的回报 - 除第7行外,我获得了所有行。:/ – errata 2012-05-01 01:18:56