前面的內容,我們了解了使用urllib3和selenium來下載網(wǎng)頁,但下載下來的是整個網(wǎng)頁的內容,那我們又怎么從下載下來的網(wǎng)頁中提取我們自己感興趣的內容呢?這里就需要Python的另一個庫來實現(xiàn)-BeautifulSoup。
BeautifulSoup 是一個 Python 庫,用于分析 HTML。它和它的名字一樣,用起來非常“香”。今天我們通過使用 BeautifulSoup 去從上一篇文章案例中下載到的 html 文件:jiandan.html 中提取所有新聞的標題。
打開 VS Code,并創(chuàng)建ipynb文件,將之前下載的jandan.html文件復制到源文件共同的文件夾內。
接下來我們將在這個 notebook 中對 jiandan.html 進行內容提取。
1、安裝BeautifulSoup
這里安裝的步驟和之前安裝selenium的步驟一樣。
我們去開始菜單 → Anaconda ,選擇 Anaconda Prompt,出現(xiàn)命令行界面。在命令行界面,輸入如下安裝命令:(BeautifulSoup 的 Python 包名為 bs4, 簡寫)
conda install bs4
回車執(zhí)行,之后在詢問會否確認時輸入 y 回車,等待安裝完畢,關閉即可。
(1)讀取html文件到Python
數(shù)據(jù)提取的第一步,我們首先需要將 html 文件加載到 Python 的變量中。在上一篇文章中,我們了解了通過文件對象來把 Python 變量寫進文件里,這里我們來嘗試用類似的代碼來將文件中的內容讀出來。
代碼如下,可以看到和寫入文件的代碼非常類似。
#?打開?jiandan.html,第二個參數(shù)?r,代表?read
#?open?函數(shù)返回一個文件對象,保存在變量?fo?中
fo?=?open("jiandan.html","r",encoding="utf-8")
#?調用文件對象的?read?函數(shù),該函數(shù)將文件的內容讀取到?Python?中
#?read?函數(shù)的返回值就會文件內容,我們保存在?html_content?中
html_content?=?fo.read()
#?關閉文件對象
fo.close()
#?打印?html_content?變量,看內容是否被正確加載
print(html_content)
執(zhí)行之后,輸出結果如下所示(打印的 html 文本太長,這里僅截圖示意)。
(2)創(chuàng)建BeautifulSoup對象
現(xiàn)在,我們已經(jīng)將文件的內容讀了出來,但是目前還是以一個超大的字符串的形式存儲在變量中。想要對其進行有效的分析,第一步我們先要構造一個 BeautifulSoup 的對象。代碼如下:
#?從?bs4?模塊中導入?BeautifulSoup?類
from?bs4?import?BeautifulSoup
#?創(chuàng)建一個?BeautifulSoup?的對象,并將剛才我們存儲網(wǎng)頁內容的變量作為參數(shù)
doc?=?BeautifulSoup(html_content)
#?打印?doc?對象的?title?屬性。
print(doc.title)
執(zhí)行上述代碼之后,BeautifulSoup 對象就被創(chuàng)建并存在變量 doc 中,為了測試是否創(chuàng)建成功,我們打印了 doc 對象的 title 屬性,輸出如下。
<title>
煎蛋 - 地球上沒有新鮮事
</title>
(3)BeautifulSoup 對象的基本使用
剛剛我們打印了 doc 對象的 title 屬性,來測試對象是否創(chuàng)建成功。從打印的內容來看,想必你已經(jīng)猜到了,doc 對象的 title 屬性,就對應了網(wǎng)頁的 title 標簽。但是剛才我們打印的內容中,title 標簽也被打印出來了。
那是否可以只取標簽里面的內容呢?
①get_text方法
在 BeautifulSoup 中,我們可以通過標簽對象的 get_text 方法來獲得標簽中的內容。
# 將 title 屬性保存在 title_label 的變量中
title_label?=?doc.title
# 調用 get_text 方法,并把返回值打印出來
print(title_label.get_text())
輸出如下:
煎蛋 - 地球上沒有新鮮事
可以看到,這次我們成功將標簽內的文字提取了出來。
②find_all方法
BeautifulSoup 對象另一個常用方法是 find_all, 用來在 html 文檔中查到特定標簽名以及特定屬性值的標簽,下面來舉例說明。
比如,在網(wǎng)頁上有這么個結構
目前我們的 doc 對象已經(jīng)包含了這些內容。現(xiàn)在我們來嘗試提取 class 等于 logo 的這個 div 標簽,代碼如下。
#?find_all?是?BeautifulSoup?對象的常用方法,用于查找特定的標簽
#?接受三個參數(shù),第一個是要查找的標簽名,第二個則是要匹配的屬性名
#?比如這里,我們查找的是?class=logo?標簽,則直接按如下寫法即可。
#?因為?class?是?Python?的關鍵字,所以這里需要使用?class_?以示區(qū)分
#?最終,find_all?函數(shù)返回所有滿足條件的標簽列表
logo_label?=?doc.find_all("div",?class_="logo")
print(logo_label)
輸出結果為:
[<div class="logo">
<h1><a href="/" onclick="ga('send', 'pageview','/header/logo');">煎蛋</a></h1>
</div>]
可以看到,我們截圖中的內容,箭頭所指的 div 標簽被成功的過濾了出來。
③獲取標簽對象的屬性
通過標簽對象的 attrs 屬性,我們可以獲取標簽對象的屬性的值,attrs 是一個字典,獲取屬性的值的方法如下:
#?取?logo_label?列表的第一個標簽對象
label?=?logo_label[0]
#?打印這個對象的?class?屬性
print(label.attrs["class"])
輸出:
['logo']
2、過濾出網(wǎng)頁的新聞列表
現(xiàn)在,我們來使用之前的 doc 對象來過濾出新聞的標題列表。
(1)觀察html,提取初步的新聞標簽列表
在使用 BeautifulSoup 進行內容過濾的第一步,首先要查看我們想要的內容所在的標簽。我們在 VS Code 中打開 jiandan.html,搜索“普通感冒”到達新聞標題內容區(qū)域,如下圖所示。
通過觀察截圖中的標簽內容,很容易發(fā)現(xiàn)似乎每個新聞標題,都有一個對應的 div 標簽,并且它的 class 是 indexs。沿著這個思路,我們可以先考慮使用 find_all 將其過濾出來。通過如下代碼。
#?查找?class?為?indexs?的所有?div?標簽,存儲在?index_labels?中
index_labels?=?doc.find_all("div",?class_="indexs")
#?打印符合條件的?div?標簽的數(shù)量
print(len(index_labels))
輸出:
24
說明找到了 24 個符合條件的 div 標簽。一個網(wǎng)頁的新聞也是 20 多條,說明有希望。
(2)提取單個標簽的新聞標題
因為 index_labels 是一個標簽對象的列表,距離我們要過濾的新聞標題還有距離。下一步,我們就來分析如何從這些標簽對象中抽取新聞標題。
首先,我們先取第一個來看一下。
first_object?=?index_labels[0]
print(first_object)
輸出如下:
<div class="indexs">
<span class="comment-link" title="1小時 ago">8</span>
<h2><a target="_blank">引發(fā)普通感冒的鼻病毒會將新冠病毒排擠出細胞!</a></h2>
<div class="time_s"><a >majer</a> · <strong><a rel="tag">新冠病毒</a></strong></div>
換而言之,如果你感冒了,在那段期間就不會被新冠病毒感染 </div>
現(xiàn)在我們的問題就轉化為,如何從上述 html 中抽取出新聞的標題。
通過查看上述內容可以發(fā)現(xiàn),我們的標題在第三行,在一個 a 標簽內部。那是不是我們只需要過濾出這個 a 標簽,再使用 get_text 拿到里面的內容就好了?
那要怎么過濾出第三行的 a 標簽呢?可以看到這個 a 標簽里有 target=“_blank” 這樣一個屬性,我們就可以使用 find_all 將其過濾出來了。
#?從剛才的?first_object?標簽對象中過濾出所有?target=_blank?的?a?標簽
a_labels?=?first_object.find_all("a",target="_blank")
#?取第一個標簽對象
my_label?=?a_labels[0]
#?打印該標簽對象內的文字內容
print(my_label.get_text())
輸出如下:
引發(fā)普通感冒的鼻病毒會將新冠病毒排擠出細胞!
你看,新聞的標題被成功抽取了出來!
(3)提取新聞標題的列表
目前,我們已經(jīng)實現(xiàn)了從第一個標簽對象中提取新聞標題,但我們的列表中有 24 個標簽對象。要怎么做呢?聰明的你應該想到了,我們只需要把“從標簽對象抽取標題”這段邏輯寫成一個函數(shù),然后通過一個循環(huán)對列表的每個標簽對象都調用這個函數(shù)即可。
#?從第一次?find_all?獲取的標簽對象中抽取標題
def?get_title(label_object):
????#?從剛才的參數(shù)傳入的標簽對象中過濾出所有?target=_blank?的?a?標簽
????a_labels?=?label_object.find_all("a",target="_blank")
????#?取第一個標簽對象
????my_label?=?a_labels[0]
????#?將標簽的文字內容作為返回值返回
????return?my_label.get_text()
#?用循環(huán)針對每個?index_labels?列表中的標簽對象
#?都將其作為參數(shù)傳入?get_title?函數(shù)
#?并打印返回值
for?i?in?range(0,len(index_labels)):
????title?=?get_title(index_labels[i])
????print(title)
執(zhí)行后輸出:
引發(fā)普通感冒的鼻病毒會將新冠病毒排擠出細胞!
無厘頭研究:植入虛假的記憶再抹去它們
什么是仇恨犯罪?
突發(fā):LHCb發(fā)現(xiàn)了違背標準模型的現(xiàn)象
今日帶貨 20210324
舌戰(zhàn)裸猿:IBM搞出了可以打辯論賽的AI
大吐槽:「我沒醉,醉的是世界」
今年世界總發(fā)電量的0.6%被用于挖比特幣
接種疫苗后還是感染新冠?不要為此驚訝
今日帶貨:蛋友家的血橙
科學家首次在野外檢測到抗多藥的超級真菌
未在iPhone12盒中搭配充電器,蘋果被巴西消協(xié)罰200萬美元
工程師將解決城市陷坑的問題
今日帶貨:粉面專場
科學家在碟子里培育出了淚腺,并讓它哭泣
瘋狂實驗進行時:把志愿者禁閉在黑暗的空間里40天
今日帶貨 20210321
我們已向外星人發(fā)送了哪些消息?
腦力小體操:石頭+剪刀 VS 石頭+布
發(fā)霉啦:今天,我終于向母親攤牌了
普渡大學的經(jīng)濟學家計算出世界各地幸福的價格
人類首次觀察到木星上極光黎明風暴的成形過程
為女兒出頭,母親編輯假裸照敗壞高中啦啦隊隊員的名譽
今日帶貨:淘寶京東蛋友推薦
可以看到,jiandan.html 中的所有新聞標題被我們成功過濾了出來,現(xiàn)在是不是感受到了 BeautifulSoup 的神奇之處了呢。文章來源:http://www.zghlxwxcb.cn/news/detail-799854.html
至此,我們就完成了使用 BeautifulSoup 對網(wǎng)頁進行內容的提取。文章來源地址http://www.zghlxwxcb.cn/news/detail-799854.html
到了這里,關于快樂學Python,如何使用爬蟲從網(wǎng)頁中提取感興趣的內容?的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!