2012-01-25 28 views
20

Tôi có html (ngắt dòng được đánh dấu bằng \ n) như sau:Cách tìm thẻ có văn bản cụ thể bằng Beautiful Soup?

... 
<tr> 
    <td class="pos">\n 
     "Some text:"\n 
     <br>\n 
     <strong>some value</strong>\n 
    </td> 
</tr> 
<tr> 
    <td class="pos">\n 
     "Fixed text:"\n 
     <br>\n 
     <strong>text I am looking for</strong>\n 
    </td> 
</tr> 
<tr> 
    <td class="pos">\n 
     "Some other text:"\n 
     <br>\n 
     <strong>some other value</strong>\n 
    </td> 
</tr> 
... 

Làm thế nào để tìm văn bản Tôi đang tìm kiếm? Mã bên dưới trả về giá trị được tìm thấy đầu tiên, vì vậy tôi cần lọc theo Văn bản cố định bằng cách nào đó.

result = soup.find('td', {'class' :'pos'}).find('strong').text 

Upd. Nếu tôi sử dụng đoạn mã sau:

title = soup.find('td', text = re.compile(ur'Fixed text:(.*)', re.DOTALL), attrs = {'class': 'pos'}) 
self.response.out.write(str(title.string).decode('utf8')) 

sau đó nó sẽ trả về chỉ cố định văn bản:.

+0

Bạn cần sử dụng 'findAll'. – JBernardo

Trả lời

21

Bạn có thể vượt qua một biểu thức chính quy để tham số văn bản của findAll, như vậy:

import BeautifulSoup 
import re 

columns = soup.findAll('td', text = re.compile('your regex here'), attrs = {'class' : 'pos'}) 
+0

Cảm ơn, Peter. Nhưng nó tìm thấy ** Cố định văn bản: ** trong kết quả và không ** văn bản tôi đang tìm **. –

+0

Đây là câu trả lời được đánh dấu, nhưng không giải quyết được câu hỏi. Câu trả lời là trong bài mặc dù – Nitay

+0

@LA_ Là 'soup.find (...)' bắt đầu với thẻ 'body' hoặc từ gốc html? – Sajad

21

bài này đã cho tôi câu trả lời của tôi mặc dù câu trả lời là mất tích từ bài đăng này. Tôi cảm thấy mình nên trả lại.

Thách thức ở đây là trong hành vi không nhất quán của BeautifulSoup.find khi tìm kiếm có và không có văn bản.

Lưu ý: Nếu bạn có BeautifulSoup, bạn có thể kiểm tra điều này tại địa phương thông qua:

curl https://gist.githubusercontent.com/RichardBronosky/4060082/raw/test.py | python 

Code:https://gist.github.com/4060082

# Taken from https://gist.github.com/4060082 
from BeautifulSoup import BeautifulSoup 
from urllib2 import urlopen 
from pprint import pprint 
import re 

soup = BeautifulSoup(urlopen('https://gist.githubusercontent.com/RichardBronosky/4060082/raw/test.html').read()) 
# I'm going to assume that Peter knew that re.compile is meant to cache a computation result for a performance benefit. However, I'm going to do that explicitly here to be very clear. 
pattern = re.compile('Fixed text') 

# Peter's suggestion here returns a list of what appear to be strings 
columns = soup.findAll('td', text=pattern, attrs={'class' : 'pos'}) 
# ...but it is actually a BeautifulSoup.NavigableString 
print type(columns[0]) 
#>> <class 'BeautifulSoup.NavigableString'> 

# you can reach the tag using one of the convenience attributes seen here 
pprint(columns[0].__dict__) 
#>> {'next': <br />, 
#>> 'nextSibling': <br />, 
#>> 'parent': <td class="pos">\n 
#>>  "Fixed text:"\n 
#>>  <br />\n 
#>>  <strong>text I am looking for</strong>\n 
#>> </td>, 
#>> 'previous': <td class="pos">\n 
#>>  "Fixed text:"\n 
#>>  <br />\n 
#>>  <strong>text I am looking for</strong>\n 
#>> </td>, 
#>> 'previousSibling': None} 

# I feel that 'parent' is safer to use than 'previous' based on http://www.crummy.com/software/BeautifulSoup/bs4/doc/#method-names 
# So, if you want to find the 'text' in the 'strong' element... 
pprint([t.parent.find('strong').text for t in soup.findAll('td', text=pattern, attrs={'class' : 'pos'})]) 
#>> [u'text I am looking for'] 

# Here is what we have learned: 
print soup.find('strong') 
#>> <strong>some value</strong> 
print soup.find('strong', text='some value') 
#>> u'some value' 
print soup.find('strong', text='some value').parent 
#>> <strong>some value</strong> 
print soup.find('strong', text='some value') == soup.find('strong') 
#>> False 
print soup.find('strong', text='some value') == soup.find('strong').text 
#>> True 
print soup.find('strong', text='some value').parent == soup.find('strong') 
#>> True 

Mặc dù nó là chắc chắn nhất quá muộn để giúp OP, tôi hy vọng họ sẽ làm điều này như là câu trả lời vì nó đáp ứng tất cả các quandaries xung quanh việc tìm kiếm bằng văn bản.

+10

@BrunoBronosky, Đã 5 năm và bạn vẫn quay lại tài liệu này mà bạn đã thực hiện. Cảm ơn bạn đã dành thời gian để viết này. Bạn thực sự đánh giá cao bản thân. –

+5

@BrunoBronosky Tôi biết, nhưng cảm ơn bạn đã nói như vậy. –

+1

Cảm ơn, điều đó đã cho tôi một tiếng cười tốt. #SameBoat – aneroid

Các vấn đề liên quan