2017-08-31 4 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 

あなたはテーブルがいずれかのクラス=「テスト隠された」またはクラス=「フル」が列を持っていることがわかります。私は 'hidden'が要素のクラスではない行をすべて取得しようとしています。

基本的に私は出力になりたい:代わり

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

私は "ないで" の複数の組み合わせを試してみたのか"!="。私はラムダが呼び出す関数を作成しようとしたので、xがどんな型のオブジェクトであるかを知ることができ、それを扱う方法をよりよく理解できますが、ラムダをハードコードしない限り、ラムダxのようなもの:x == 'testabc'またはx == 'testxyz'

これは私が試みていることをすることは可能ですか?誰かが私を正しい方向に向けることができますか?

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> 

答えて

1

problremがclass_ということです

+0

これは素晴らしいです!あなたの最初の例でラムダを使用しました。それは "エレガント"ではないが、それはそれが悪いとは思わない。他の方法ではなく、このようにしなければならないのはちょっと奇妙です。私が元々書いたものにかなり近いです。 ありがとう!これまでのPythonを愛して、わずか数日で... – tjans

+0

ええ、pythonは素晴らしいです。私は数年前からそれを使っていますが、今でも新しいことを生きています! –

+0

合意。私はちょうどそれに入るのを始めましたが、私は、自動化や他の楽しみの点で、私の未来においてすばらしいことを見ます。再度、感謝します。 – tjans

2

あなたはこのようにそれを行うことができます(TR要素は、あなたがしたくないものをフィルタリングLL取得)引数はattrs['class']リストの最初の文字列のみを使用します。
.get('class')を使用して、クラスの完全なリストにアクセスできます。

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

ええ、私は他に何も働いていない場合、私はそれを行うだろうな方法だろう考え出したが、それは何かのように見えたラムダを使用して

特別な作業をせずに済ますことができます。あなたがループでやっていることは、ラムダに適用しようとしたのと同じロジックなので、ループ中で見つかったときとチェックしている間に何かがうまく動かないようです。 – tjans