Cách tìm các thẻ chỉ có một số thuộc tính nhất định - BeautifulSoup


84

Bằng cách sử dụng BeautifulSoup, tôi sẽ tìm kiếm các thẻ CHỈ chứa các thuộc tính mà tôi tìm kiếm như thế nào?

Ví dụ, tôi muốn tìm tất cả <td valign="top">các thẻ.

Đoạn mã sau: raw_card_data = soup.fetch('td', {'valign':re.compile('top')})

nhận tất cả dữ liệu tôi muốn, nhưng cũng lấy bất kỳ <td>thẻ nào có thuộc tínhvalign:top

Tôi cũng đã thử: raw_card_data = soup.findAll(re.compile('<td valign="top">')) và điều này không trả lại gì (có thể là do regex xấu)

Tôi tự hỏi liệu có cách nào trong BeautifulSoup để nói "Tìm <td>thẻ có thuộc tính duy nhất là valign:top" không

CẬP NHẬT FOr ví dụ, nếu một tài liệu HTML chứa các <td>thẻ sau :

<td valign="top">.....</td><br />
<td width="580" valign="top">.......</td><br />
<td>.....</td><br />

Tôi chỉ muốn <td>thẻ đầu tiên ( <td width="580" valign="top">) trả về

Câu trả lời:


96

Như đã giải thích trên tài liệu BeutifulSoup

Bạn có thể sử dụng cái này:

soup = BeautifulSoup(html)
results = soup.findAll("td", {"valign" : "top"})

BIÊN TẬP :

Để trả về các thẻ chỉ có thuộc tính valign = "top", bạn có thể kiểm tra độ dài của thuộc tính thẻ attrs:

from BeautifulSoup import BeautifulSoup

html = '<td valign="top">.....</td>\
        <td width="580" valign="top">.......</td>\
        <td>.....</td>'

soup = BeautifulSoup(html)
results = soup.findAll("td", {"valign" : "top"})

for result in results :
    if len(result.attrs) == 1 :
        print result

Điều đó trả lại:

<td valign="top">.....</td>

Theo nhận xét của tôi cho julio.alegria, Điều này sẽ tìm thấy tất cả <tr>các thẻ có thuộc tính valign="top", bao gồm cả những thẻ có thuộc tính khác ( <td width="580" valign="top">cũng được trả về trong tìm kiếm này) Tôi đang tìm một phương pháp để tìm <tr>các thẻ có thuộc tính duy nhất làvalign="top"
Snaxib 19/01

Vì vậy, bạn có thể kiểm tra len (tag.attrs). Nếu len (tag.attrs)> 1, bỏ qua các thẻ (Tôi đã chỉnh sửa bài viết của tôi)
Loïc G.

51

Bạn có thể sử dụng các lambdahàm trong findAllnhư được giải thích trong tài liệu . Vì vậy, trong trường hợp của bạn để tìm kiếm tdthẻ chỉ valign = "top"sử dụng sau:

td_tag_list = soup.findAll(
                lambda tag:tag.name == "td" and
                len(tag.attrs) == 1 and
                tag["valign"] == "top")

4
Câu trả lời tốt nhất vì nó sử dụng toàn bộ sức mạnh của BS
Rafael T

2
Câu trả lời tuyệt vời vì nó mang lại cho bạn kết quả theo cách rất tối ưu hóa.
CrazyGeek

32

nếu bạn chỉ muốn tìm kiếm với tên thuộc tính với bất kỳ giá trị nào

from bs4 import BeautifulSoup
import re

soup= BeautifulSoup(html.text,'lxml')
results = soup.findAll("td", {"valign" : re.compile(r".*")})

theo Steve Lorimer tốt hơn nên chuyển True thay vì regex

results = soup.findAll("td", {"valign" : True})

2
Bạn thiếu dấu ngoặc sau r".*", dẫn đến việc này không được biên dịch.
Jack Cole

9
Không cần biểu thức chính quy, chỉ cần chuyển True:results = soup.findAll("td", {"valign" : True})
Steve Lorimer

14

Cách dễ nhất để làm điều này là với selectphương pháp kiểu CSS mới :

soup = BeautifulSoup(html)
results = soup.select('td[valign="top"]')

4

Chỉ cần chuyển nó như một đối số của findAll:

>>> from BeautifulSoup import BeautifulSoup
>>> soup = BeautifulSoup("""
... <html>
... <head><title>My Title!</title></head>
... <body><table>
... <tr><td>First!</td>
... <td valign="top">Second!</td></tr>
... </table></body><html>
... """)
>>>
>>> soup.findAll('td')
[<td>First!</td>, <td valign="top">Second!</td>]
>>>
>>> soup.findAll('td', valign='top')
[<td valign="top">Second!</td>]

1
Điều gì sẽ xảy ra nếu có các thẻ như vậy <td width="580" valign="top">:? Tôi không muốn lấy những, chỉ cần thẻ có thuộc tính duy nhất làvalign="top"
Snaxib

2

Thêm sự kết hợp giữa câu trả lời của Chris Redford và Amr, bạn cũng có thể tìm kiếm tên thuộc tính với bất kỳ giá trị nào bằng lệnh select:

from bs4 import BeautifulSoup as Soup
html = '<td valign="top">.....</td>\
    <td width="580" valign="top">.......</td>\
    <td>.....</td>'
soup = Soup(html, 'lxml')
results = soup.select('td[valign]')

Tôi đã thử theo cách tương tự nhưng cách này không hiệu quả, có cách giải quyết nào không?
Phaneendra Charyulu Kanduri

1
@PhaneendraCharyuluKanduri Rất tiếc, đã xảy ra lỗi viết sai trong mã. Bây giờ sao chép và dán sẽ hoạt động!
GrazingScientist
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.