前不久,我在 LearnML 子論壇上看到一篇帖子。樓主在這篇帖子中提到,他需要為自己的機器學習項目抓取網頁數據。很多人在回帖中給出了自己的方法,主要是學習如何使用 BeautifulSoup 和 Selenium。
我曾在一些 數據科學項目中使用過 BeautifulSoup 和 Selenium。在本文中,我將告訴你如何用一些有用的數據抓取一個網頁,並將其轉換成 pandas 數據結構(DataFrame)。
為什麼要將其轉換成數據結構呢?這是因為大部分機器學習庫都能處理 pandas 數據結構,並且只需少量修改就可對你的模型進行編輯。
首先,我們要在維基百科上找到一個表來轉換成數據結構。我抓取的這張表,展示的是維基百科上瀏覽量最大的運動員數據。

其中一項大量的工作就是,通過瀏覽 HTML 樹來得到我們需要的表。

通過 request 和 regex 庫,我們開始使用 BeautifulSoup。
from bs4 import BeautifulSoup
import requests
import re
import pandas as pd
複製代碼
下面,我們將從網頁中提取 HTML 代碼:
website_url = requests.get('https://en.wikipedia.org/wiki/Wikipedia:Multiyear_ranking_of_most_viewed_pages').text
soup = BeautifulSoup(website_url, 'lxml')
print(soup.prettify())
</a>
</li>
<li id="footer-places-disclaimer">
<a href="/wiki/Wikipedia:General_disclaimer" title="Wikipedia:General disclaimer">
Disclaimers
</a>
</li>
<li id="footer-places-contact">
<a href="//en.wikipedia.org/wiki/Wikipedia:Contact_us">
Contact Wikipedia
</a>
</li>
<li id="footer-places-mobileview">
<a class="noprint stopMobileRedirectTog
複製代碼
從語料庫中收集所有的表,我們有一個較小的表面區域來搜索。
wiki_tables = soup.find_all('table', class_='wikitable')
wiki_tables
複製代碼
因為存在很多表,所以需要一種過濾它們的方法。
據我們所知,Cristiano Ronaldo(也就是葡萄牙足球運動員 C 羅)有一個錨標記,這可能在幾個表中是獨一無二的。

通過 Cristiano Ronaldo 文本,我們可以過濾那些被錨標記的表。此外,我們還發現一些包含這個錨標記的父元素。
links = []
for table in wiki_tables:
_table = table.find('a', string=re.compile('Cristiano Ronaldo'))
if not _table:
continue
print(_table)
_parent = _table.parent
print(_parent)
links.append(_parent)
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>
複製代碼
父元素只顯示單元格。
這是一個帶有瀏覽器 web 開發工具的單元格。

parent_lst = []
for anchor in links:
_ = anchor.find_parents('tbody')
print(_)
parent_lst.append(_)
複製代碼
利用 tbody,我們可以返回包含以前的錨標記的其他表。
為進一步過濾,我們可以在以下表中的不同標題進行搜索:
for i in parent_lst:
print(i[0].find('tr'))
tr>
<th>Rank*</th>
<th>Page</th>
<th>Views in millions
</th></tr>
<tr>
<th>Rank</th>
<th>Page</th>
<th>Views in millions
</th></tr>
<tr>
<th>Rank</th>
<th>Page</th>
<th>Sport</th>
<th>Views in millions
</th></tr>
複製代碼
第三張看起來很像我們所需要的表。
接下來,我們開始創建必要的邏輯來提取並清理我們需要的細節。
sports_table = parent_lst[2]
complete_row = []
for i in sports_table:
rows = i.find_all('tr')
print('n--------row--------n')
print(rows)
for row in rows:
cells = row.find_all('td')
print('n-------cells--------n')
print(cells)
if not cells:
continue
rank = cells[0].text.strip('n')
page_name = cells[1].find('a').text
sport = cells[2].find('a').text
views = cells[3].text.strip('n')
print('n-------CLEAN--------n')
print(rank)
print(page_name)
print(sport)
print(views)
complete_row.append([rank, page_name, sport, views])
for i in complete_row:
print(i)
複製代碼
分解一下:
sports_table = parent_lst[2]
complete_row = []
複製代碼
下面我們從上面的列表中選擇第三個元素。這就是我們需要的表。
接下來創建一個空列表,用於存儲每行的詳細信息。在遍歷這個表的時候,建立一個循環,遍歷表中的每一行,並將其保存到 rows 變數中。
for i in sports_table:
rows = i.find_all('tr')
print('n--------row--------n')
print(rows)
複製代碼

for row in rows:
cells = row.find_all('td')
print('n-------cells--------n')
print(cells)
複製代碼
建立了嵌套的循環。遍歷上一個循環中保存的每個行。在遍歷這些單元格時,我們將每個單元格保存在一個新的變數。

if not cells:
continue
複製代碼
這段簡短的代碼允許我們在從單元格中提取文本時,避免空單元格並防止發生錯誤。
rank = cells[0].text.strip('n')
page_name = cells[1].find('a').text
sport = cells[2].find('a').text
views = cells[3].text.strip('n')
複製代碼
在此,我們將各種單元格清理為純文本格式。清除後的值保存在其列名下的變數中。
print('n-------CLEAN--------n')
print(rank)
print(page_name)
print(sport)
print(views)
complete_row.append([rank, page_name, sport, views])
複製代碼
此處,我們向行列表添加這些值。然後輸出清理後的值。
-------cells--------
[<td>13
</td>, <td style="text-align: left;"><a href="/wiki/Conor_McGregor" title="Conor McGregor">Conor McGregor</a>
</td>, <td><a href="/wiki/Mixed_martial_arts" title="Mixed martial arts">Mixed martial arts</a>
</td>, <td>43
</td>]
-------CLEAN--------
13
Conor McGregor
Mixed martial arts
43
複製代碼
下面將其轉換為數據結構:
headers = ['Rank', 'Name', 'Sport', 'Views Mil']
df = pd.DataFrame(complete_row, columns=headers)
df
複製代碼

現在你可以在機器學習項目中使用的 pandas 數據結構了。你可以使用自己喜歡的庫來擬合模型數據。
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/280987.html