2017-08-31 69 views
1

我試圖讓BS4過濾元素出包含某個類。這裏是我的HTML:Python2與美麗的湯 - 過濾元素與多個CSS類

<!-- language: lang-html --> 
<html> 
<head> 
    <title>Test</title> 
</head> 

<body> 

<table> 
    <tr class='test hidden'><td>foo</td></tr> 
    <tr class='testabc'><td>bar</td></tr> 
    <tr class='test hidden'><td>foo</td></tr> 
    <tr class='testxyz'><td>bar</td></tr> 
</table> 

</body> 

</html> 

我的Python代碼:

# import libraries 
import urllib2 
import re 
from bs4 import BeautifulSoup 
from bs4 import Comment 
import operator 

with open('sample.html', 'r') as myfile: 
    html=myfile.read() 

soup = BeautifulSoup(html, 'html.parser') 
rows = soup.find('table').find_all('tr', class_=lambda x: 'hidden' not in x) 

for row in rows: 
    print row 

可以看到,表中有任一類=「測試隱藏」或類=「全」行。我試圖讓所有'隱藏'不是元素上的類的行。

基本上我想要的輸出是:

<tr class='testabc'><td>bar</td></tr> 
<tr class='testxyz'><td>bar</td></tr> 

相反,我得到的所有行:

<tr class='test123 hidden'><td>foo</td></tr> 
<tr class='testabc'><td>bar</td></tr> 
<tr class='test456 hidden'><td>foo</td></tr> 
<tr class='testxyz'><td>bar</td></tr> 

我 「不是」 嘗試過多種組合或「!=」。我試過創建一個lambda調用的函數,所以我可以看到x是什麼類型的對象,並更好地理解如何使用它,但是我不能讓它工作,除非我硬編碼lambda到像lambda x:x =='testabc'或x =='testxyz'

這是可能做我想要的嗎?有人能指引我朝着正確的方向嗎?

回答

1

的problrem是,class_參數只使用attrs['class']列表中的第一個字符串。
您可以使用.get('class')來訪問完整的課程列表。

使用Lambda:

rows = soup.find('table').find_all(
    lambda tag: tag.name == 'tr' and 'hidden' not in tag.get('class', '') 
) 

使用列表理解:

rows = [ 
    tr for tr in soup.find('table').find_all('tr') if 'hidden' not in tr.get('class', '') 
] 
+0

這很好用!我在第一個例子中使用了lambda。這不是「優雅」,但我認爲它不是那麼糟糕。有點奇怪,它必須以這種方式來完成,而不是以其他方式完成。這與我原本寫的很接近。 謝謝!愛到目前爲止,只有幾天它進入它... – tjans

+0

是的,蟒蛇是驚人的。我現在使用它已經有好幾年了,但每天仍然會帶來新的東西! –

+0

同意。我剛開始接觸它,但在自動化和其他樂趣方面,我看到了未來的偉大之處。再次感謝。 – tjans

2

你可以像下面這樣做(讓LL的TR元素,然後過濾掉你不想要的):

from bs4 import BeautifulSoup 

html = """ 
<html> 
<head> 
    <title>Test</title> 
</head> 

<body> 

<table> 
    <tr class='test hidden'><td>foo</td></tr> 
    <tr class='testabc'><td>bar</td></tr> 
    <tr class='test hidden'><td>foo</td></tr> 
    <tr class='testxyz'><td>bar</td></tr> 
</table> 

</body> 

</html> 
""" 

soup = BeautifulSoup(html, 'html.parser') 
rows = soup.find('table').find_all('tr') 

for row in rows: 
    if 'hidden' not in row.attrs['class']: 
     print row 

輸出:

<tr class="testabc"><td>bar</td></tr> 
<tr class="testxyz"><td>bar</td></tr> 
+0

是啊,我想那會是我會做,如果沒有其他的工作方式,但它似乎像什麼這可以在沒有額外工作的情況下完成。好像你在循環中做的是和我試圖應用到lambda相同的邏輯,所以當它在循環中查找和檢查期間被應用時,似乎有些東西不適用。 – tjans