Beautiful Soup - Tìm kiếm cây
Có nhiều phương thức Beautifulsoup, cho phép chúng ta tìm kiếm một cây phân tích cú pháp. Hai phương thức phổ biến và được sử dụng nhiều nhất là find () và find_all ().
Trước khi nói về find () và find_all (), chúng ta hãy xem một số ví dụ về các bộ lọc khác nhau mà bạn có thể chuyển vào các phương thức này.
Các loại bộ lọc
Chúng tôi có các bộ lọc khác nhau mà chúng tôi có thể chuyển vào các phương pháp này và sự hiểu biết về các bộ lọc này là rất quan trọng vì các bộ lọc này được sử dụng nhiều lần trong suốt API tìm kiếm. Chúng tôi có thể sử dụng các bộ lọc này dựa trên tên thẻ, thuộc tính của thẻ, trên văn bản của một chuỗi hoặc kết hợp các bộ lọc này.
Một chuỗi
Một trong những loại bộ lọc đơn giản nhất là một chuỗi. Chuyển một chuỗi đến phương thức tìm kiếm và Beautifulsoup sẽ thực hiện đối sánh với chuỗi chính xác đó.
Đoạn mã dưới đây sẽ tìm thấy tất cả các thẻ <p> trong tài liệu -
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>> markup.find_all('p')
[<p>Top Three</p>, <p></p>, <p><b>Java, Python, Cplusplus</b></p>]
Biểu hiện thông thường
Bạn có thể tìm thấy tất cả các thẻ bắt đầu bằng một chuỗi / thẻ nhất định. Trước đó, chúng ta cần nhập mô-đun re để sử dụng biểu thức chính quy.
>>> import re
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>>
>>> markup.find_all(re.compile('^p'))
[<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>]
Danh sách
Bạn có thể chuyển nhiều thẻ để tìm bằng cách cung cấp danh sách. Đoạn mã dưới đây tìm thấy tất cả các thẻ <b> và <pre> -
>>> markup.find_all(['pre', 'b'])
[<pre>Programming Languages are:</pre>, <b>Java, Python, Cplusplus</b>]
Thật
True sẽ trả về tất cả các thẻ mà nó có thể tìm thấy, nhưng không có chuỗi của riêng chúng -
>>> markup.find_all(True)
[<html><body><p>Top Three</p><p></p><pre>Programming Languages are:</pre>
<p><b>Java, Python, Cplusplus</b> </p> </body></html>,
<body><p>Top Three</p><p></p><pre> Programming Languages are:</pre><p><b>Java, Python, Cplusplus</b></p>
</body>,
<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>, <b>Java, Python, Cplusplus</b>]
Để chỉ trả lại các thẻ từ súp trên -
>>> for tag in markup.find_all(True):
(tag.name)
'html'
'body'
'p'
'p'
'pre'
'p'
'b'
find_all ()
Bạn có thể sử dụng find_all để trích xuất tất cả các lần xuất hiện của một thẻ cụ thể từ phản hồi trang dưới dạng:
Cú pháp
find_all(name, attrs, recursive, string, limit, **kwargs)
Hãy để chúng tôi trích xuất một số dữ liệu thú vị từ IMDB- “Phim được xếp hạng cao nhất” mọi thời đại.
>>> url="https://www.imdb.com/chart/top/?ref_=nv_mv_250"
>>> content = requests.get(url)
>>> soup = BeautifulSoup(content.text, 'html.parser')
#Extract title Page
>>> print(soup.find('title'))
<title>IMDb Top 250 - IMDb</title>
#Extracting main heading
>>> for heading in soup.find_all('h1'):
print(heading.text)
Top Rated Movies
#Extracting sub-heading
>>> for heading in soup.find_all('h3'):
print(heading.text)
IMDb Charts
You Have Seen
IMDb Charts
Top India Charts
Top Rated Movies by Genre
Recently Viewed
Từ phía trên, chúng ta có thể thấy find_all sẽ cung cấp cho chúng ta tất cả các mục phù hợp với tiêu chí tìm kiếm mà chúng ta xác định. Tất cả các bộ lọc chúng ta có thể sử dụng với find_all () đều có thể được sử dụng với find () và các phương thức tìm kiếm khác như find_arent () hoặc find_siblings ().
tìm thấy()
Chúng ta đã thấy ở trên, find_all () dùng để quét toàn bộ tài liệu để tìm tất cả nội dung nhưng có điều, yêu cầu là chỉ tìm được một kết quả. Nếu bạn biết rằng tài liệu chỉ chứa một thẻ <body>, thì sẽ lãng phí thời gian để tìm kiếm toàn bộ tài liệu. Một cách là gọi find_all () với limit = 1 mọi lúc, nếu không, chúng ta có thể sử dụng phương thức find () để thực hiện tương tự -
Cú pháp
find(name, attrs, recursive, string, **kwargs)
Vì vậy, dưới đây hai phương pháp khác nhau cho cùng một đầu ra -
>>> soup.find_all('title',limit=1)
[<title>IMDb Top 250 - IMDb</title>]
>>>
>>> soup.find('title')
<title>IMDb Top 250 - IMDb</title>
Trong các kết quả đầu ra ở trên, chúng ta có thể thấy phương thức find_all () trả về một danh sách chứa một mục duy nhất trong khi phương thức find () trả về một kết quả.
Một sự khác biệt khác giữa phương thức find () và find_all () là -
>>> soup.find_all('h2')
[]
>>>
>>> soup.find('h2')
Nếu phương thức soup.find_all () không tìm thấy gì, nó trả về danh sách trống trong khi find () trả về None.
find_arent () và find_parent ()
Không giống như các phương thức find_all () và find () đi ngang qua cây, nhìn vào con của thẻ, các phương thức find_arent () và find_arent () làm ngược lại, chúng đi ngang cây lên trên và xem xét cha mẹ của một thẻ (hoặc một chuỗi).
Cú pháp
find_parents(name, attrs, string, limit, **kwargs)
find_parent(name, attrs, string, **kwargs)
>>> a_string = soup.find(string="The Godfather")
>>> a_string
'The Godfather'
>>> a_string.find_parents('a')
[<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>]
>>> a_string.find_parent('a')
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
>>> a_string.find_parent('tr')
<tr>
<td class="posterColumn">
<span data-value="2" name="rk"></span>
<span data-value="9.149038526210072" name="ir"></span>
<span data-value="6.93792E10" name="us"></span>
<span data-value="1485540" name="nv"></span>
<span data-value="-1.850961473789928" name="ur"></span>
<a href="/title/tt0068646/"> <img alt="The Godfather" height="67" src="https://m.media-amazon.com/images/M/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_UY67_CR1,0,45,67_AL_.jpg" width="45"/>
</a> </td>
<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>
<td class="ratingColumn imdbRating">
<strong title="9.1 based on 1,485,540 user ratings">9.1</strong>
</td>
<td class="ratingColumn">
<div class="seen-widget seen-widget-tt0068646 pending" data-titleid="tt0068646">
<div class="boundary">
<div class="popover">
<span class="delete"> </span><ol><li>1<li>2<li>3<li>4<li>5<li>6<li>7<li>8<li>9<li>10</li>0</li></li></li></li&td;</li></li></li></li></li></ol> </div>
</div>
<div class="inline">
<div class="pending"></div>
<div class="unseeable">NOT YET RELEASED</div>
<div class="unseen"> </div>
<div class="rating"></div>
<div class="seen">Seen</div>
</div>
</div>
</td>
<td class="watchlistColumn">
<div class="wlb_ribbon" data-recordmetrics="true" data-tconst="tt0068646"></div>
</td>
</tr>
>>>
>>> a_string.find_parents('td')
[<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>]
Có tám phương pháp tương tự khác -
find_next_siblings(name, attrs, string, limit, **kwargs)
find_next_sibling(name, attrs, string, **kwargs)
find_previous_siblings(name, attrs, string, limit, **kwargs)
find_previous_sibling(name, attrs, string, **kwargs)
find_all_next(name, attrs, string, limit, **kwargs)
find_next(name, attrs, string, **kwargs)
find_all_previous(name, attrs, string, limit, **kwargs)
find_previous(name, attrs, string, **kwargs)
Ở đâu,
find_next_siblings() và find_next_sibling() các phương thức sẽ lặp qua tất cả các anh chị em của phần tử đứng sau phần tử hiện tại.
find_previous_siblings() và find_previous_sibling() các phương thức sẽ lặp qua tất cả các anh chị em đứng trước phần tử hiện tại.
find_all_next() và find_next() các phương thức sẽ lặp lại trên tất cả các thẻ và chuỗi đứng sau phần tử hiện tại.
find_all_previous và find_previous() các phương thức sẽ lặp lại trên tất cả các thẻ và chuỗi đứng trước phần tử hiện tại.
Bộ chọn CSS
Thư viện BeautifulSoup để hỗ trợ các bộ chọn CSS thông dụng nhất. Bạn có thể tìm kiếm các phần tử bằng bộ chọn CSS với sự trợ giúp của phương thức select ().
Dưới đây là một số ví dụ -
>>> soup.select('title')
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>>
>>> soup.select("p:nth-of-type(1)")
[<p>The Top Rated Movie list only includes theatrical features.</p>, <p> class="imdb-footer__copyright _2-iNNCFskmr4l2OFN2DRsf">© 1990-2019 by IMDb.com, Inc.</p>]
>>> len(soup.select("p:nth-of-type(1)"))
2
>>> len(soup.select("a"))
609
>>> len(soup.select("p"))
2
>>> soup.select("html head title")
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>> soup.select("head > title")
[<title>IMDb Top 250 - IMDb</title>]
#print HTML code of the tenth li elemnet
>>> soup.select("li:nth-of-type(10)")
[<li class="subnav_item_main">
<a href="/search/title?genres=film_noir&sort=user_rating,desc&title_type=feature&num_votes=25000,">Film-Noir
</a> </li>]