1、上行遍歷即查找自己的父節(jié)點或者先前節(jié)點 2、下行遍歷即查找自己的子節(jié)點或者孫節(jié)點 3、平行遍歷即查找跟自己平行的節(jié)點,必須發(fā)生在同一個父親節(jié)點下
#本代碼演示BeautifulSoup的上行遍歷,下行遍歷,平行遍歷,代碼如下:
#1、導入相應(yīng)的模塊 import requests from bs4 import BeautifulSoup #2、對網(wǎng)站進行g(shù)et請求 url="http://huizhou.loupan.com" #設(shè)置網(wǎng)站為惠州樓盤網(wǎng) headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"} # 設(shè)置網(wǎng)頁請求頭 response=requests.get(url,headers=headers) ##偽裝瀏覽器對url進行g(shù)et請求 response.encoding=response.apparent_encoding #根據(jù)網(wǎng)頁內(nèi)容進行解析編碼并賦值給response.encoding html=response.text #將響應(yīng)的網(wǎng)頁源代碼賦值給html #3、對網(wǎng)站進行解析 soup=BeautifulSoup(html,"html.parser") print(soup.a) #打印a標簽 print(soup.head) #打印head標簽 print("head標簽的兒子標簽:",soup.head.contents) #打印head標簽的兒子標簽 print("a標簽的父節(jié)點:",soup.a.parent) #打印a標簽的父節(jié)點,即上行查找 print(soup.a.parent.parent) #打印a標簽的父節(jié)點的父節(jié)點,即上行查找祖先節(jié)點 print("a標簽的先前節(jié)點:",soup.a.parents) #打印a標簽的先前節(jié)點,即上行查找先前節(jié)點,包含父節(jié)點,也包含祖先節(jié)點 print("a標簽的下一個平行節(jié)點:",soup.a.next_sibling) #查找a標簽的下一個平行節(jié)點 print("div標簽的上一個平行節(jié)點:",soup.div.previous_sibling) #查找div標簽的上一個平行節(jié)點 print("a標簽的兒子節(jié)點:",soup.a.children) #打印a標簽的兒子節(jié)點,返回迭代類型 print(soup.a.contents) #打印a標簽的兒子節(jié)點,返回列表類型 print("body標簽的子孫節(jié)點:",soup.body.descendants) #打印body標簽的子節(jié)點和孫節(jié)點
碼運行結(jié)果如下圖所示:
蟲的基本框架是獲取HTML頁面信息,解析頁面信息,保存結(jié)果;bs4庫主要是解析、遍歷、提取頁面信息;bs4將復雜的HTML文檔轉(zhuǎn)化為一個樹形結(jié)構(gòu),每個節(jié)點都是一個Python對象,這些對象可以分為四類:Tag,NavigableString,Comment,BeautfifulSoup
Tag:標簽,是最基本的信息組織單元,對應(yīng)HTML原生文檔的tag,Tag的兩個基本屬性是name和attributes;
BeautfifulSoup:表示的是一個文檔的全部內(nèi)容,大部分時候可以把它當成Tag對象,但并不是真正的HTML的tag,因此沒有name和attribute屬性,但可以用.name來查看它的名字“[document]”
NavigableString:標簽內(nèi)非屬性字符串,<>-<\>內(nèi)的字符串;
Coment:Comment對象時一個特殊的NavgableString對象,表示HTML文檔的注釋部分,使用特殊的格式輸出(prettify()):
例子:
from bs4 import BeaufifulSoup soup=BeautifulSoup( tag=soup.title tag.name # 可以獲得tag 的name :'title' tag.attrs #獲取屬性:{},這個例子是空值 tag['class']='for example' #可以根據(jù)字典形式添加屬性 tag.attrs #再獲取屬性就是{‘class’: 'for example'} print(tag) #現(xiàn)在打印tag就可以得到:title class="for example">網(wǎng)易</title>
遍歷文檔樹:
下行遍歷:
1.contents:子節(jié)點的列表,把所有<tag>的所有子節(jié)點都存入列表;
2.children:子節(jié)點的迭代類型,與contents類似,遍歷子節(jié)點;
3.descendants:子孫節(jié)點的迭代類型,包含所有子孫節(jié)點,用于循環(huán)遍歷;
上行遍歷:
1.parent:獲取某元素的父親節(jié)點;
2.parents:迭代得到元素的所有父輩節(jié)點,用于循環(huán)遍歷先輩節(jié)點;
平行遍歷:
1.next_sibling:返回按照HTML文檔順序的下一個平行節(jié)點標簽
2.nex_siblings:迭代類型,返回按照HTML文檔順序的后續(xù)所有平行節(jié)點標簽;
3.previous_sibling: 返回按照HTML文檔順序的上一個平行節(jié)點標簽
4.previous_siblings: 迭代類型,返回按照HTML文檔順序的前面所有平行節(jié)點標簽;
驗說明與環(huán)境準備
在開始本次實驗之前請先完成 Python 爬蟲 1-Requests 庫入門與實戰(zhàn) 實驗
如果你尚未完成 Python 爬蟲 1-Requests 庫入門與實戰(zhàn) 實驗,請查看教程相關(guān)說明,之前的內(nèi)容將作為本次實驗的基礎(chǔ)
本次實驗需要你懂得 html 標簽的基本用法
在本教程中 bs4 庫是 Beautiful Soup4 庫的簡寫
實驗建議:
為保證實驗高效進行,請:
實驗過程中使用 ubuntu 用戶,請勿切換至 root 用戶
文件命名,目錄設(shè)定請遵循教程要求
調(diào)整命令窗口大小到合適的大小
戒驕戒躁,保持良好的心態(tài)開始本次實驗
環(huán)境準備
環(huán)境與實驗一環(huán)境相同,這里直接給出指令,這并不是教程的重點,你可以逐行復制到命令提示框中運行。
sudo apt-get updatesudo apt-get install python3 python3-pip -ypip3 install requests
安裝 Beautiful Soup 庫
關(guān)于 Beautiful Soup 庫
Beautiful Soup 是一個可以從 HTML 或 XML 文件中提取數(shù)據(jù)的 Python 庫
我們在本次實驗中使用到的解析器為 html.parser, 無需單獨安裝。
這里給出其他一些解析器,了解他們的用法請查閱相關(guān)庫說明。
lxml:lxml 的 HTML 解析器 Beautiful Soup
xml:lxml 的 XML 解析器 Beautiful Soup
html5lib:html5lib 的解析器 Beautiful Soup
解析器的選擇
Beautiful Soup 支持的解析器有以上幾種,如何選擇是我們面臨實際問題時應(yīng)該思考的問題。這里給出各庫的優(yōu)缺點,在不同的環(huán)境選擇不同的解析器是很重要的。
標準庫解析器 html.parser, 執(zhí)行速度適中,文檔容錯能力強,但 Python 2.7.3 or 3.2.2)前 的版本中文檔容錯能力差
lxml 和 xml 解析器都有著速度快的優(yōu)點,但需要安裝C語言庫,xml 解析器是唯一支持 XML 的(官方文檔中最推薦使用 lxml 解析器)
html5lib 解析器有最好的容錯性,以瀏覽器的方式解析文檔,能生成 HTML5 格式的文檔,但速度也是最慢的
Beautiful Soup 庫的安裝
使用 pip 安裝
如果你需要使用其他方式安裝,請參閱官方文檔(中文)或官方文檔(英文)。
pip3 install beautifulsoup4
!!!請注意這里是 beautifulsoup4 而不是 Beautiful Soup
pypi 中的 Beautiful Soup 是 Beautiful Soup 3版本,不是我們所需要的 bs4 版本
Beautiful Soup 庫的使用
從這里開始,請按教程提示完成操作,以便檢查器能正確識別您的操作。
溫故而知新
百度主頁爬蟲
讓我們回顧一下百度首頁(http)的爬取,在用戶目錄下創(chuàng)建 task1.py, 完成百度主頁的爬取程序,不需要輸出任何內(nèi)容。
推薦自行編寫,如果有一定困難,可以參考示例程序
請點擊 編輯 task1.py,按 Ctrl+S 可以保存
示例代碼:/home/ubuntu/task1.py
import requestsurl="http://www.baidu.com"res=requests.get(url)res.encoding=res.apparent_encoding
嘗試運行
python3 task1.py
沒有任何報錯那么我們可以進行下一步
在 Python 命令行中使用 Beautiful Soup 庫
在這一部分如果你遇到了無法解決的問題,可以嘗試 Ctrl+D 或在 Python 命令行中輸入 exit() 來退出命令行,退出后查看教程檢查器根據(jù)你之前的輸出給出的判定
讓我們先把之前的程序放一放,打開 Python 命令行
python3
導入 requests 庫并從 bs4 庫中導入 Beautiful Soup 函數(shù)
import requestsfrom bs4 import BeautifulSoup
請注意這里的庫是 bs4
完成百度首頁的爬取
res=requests.get("http://www.baidu.com")res.encoding="utf-8"
這里給出簡便的寫法
Beautiful Soup 解析網(wǎng)頁
我們先用一個變量來存放爬取到的頁面內(nèi)容
t=res.text
用 Beautiful Soup 進行解析
soup=BeautifulSoup(t,"html.parser")
P.S.如果要使用其他解析器在這里更改就對了
Beautiful Soup 解析后可以用美觀的方式輸出 html 頁面
soup.prettify()
是不是與之前直接輸出 text 要看著更好一些呢?
換行符被加上,部分頁面格式變得規(guī)范,在一定程度上增加了可讀性
標簽和標簽樹
Beautiful Soup 庫到底是一個什么庫?
它的最重要的作用并不是解析 html 頁面,從之前的內(nèi)容你也許也能意識到解析網(wǎng)頁并不是 bs4 庫所擅長的,很多時候需要其他庫的協(xié)同工作。
那么 bs4 庫是用來干什么的呢?你可能會聽到這么一種回答:解析、遍歷、維護“標簽樹”的功能庫
HTML 標簽
完成 html 標簽的操作你需要先了解 html 標簽的基本內(nèi)容,你可以參考 w3cschool 上的相關(guān)介紹了解標簽的具體用法。
標簽樹
標簽樹并不是一個嚴謹?shù)恼f法,但用樹的概念能方便我們理解對它的操作
標簽相關(guān) Part1
頁面獲取
請打開命令行,導入 requests 庫和 bs4 庫再次完成對百度主頁的爬取,如果你尚未關(guān)閉之前打開的命令行,那么可以直接繼續(xù)操作
python3
在命令行內(nèi):
import requestsfrom bs4 import BeautifulSoupres=requests.get("http://www.baidu.com")res.encoding='utf-8'soup=BeautifulSoup(res.text,'html.parser')
查看標簽
標簽是 HTML 中段落的標簽
soup.p
看看能得到什么
關(guān)于百度 About Baidu
只有一個標簽里的內(nèi)容被輸出了出來,但我們知道,百度首頁不止這一個 p 標簽
在 Python 命令行中執(zhí)行
soup.find_all('p')
查看輸出,所有
標簽都被輸出了出來,并且是以一個列表的形式
進一步嘗試
既然 find_all 返回的是一個列表,那么就可以方便的把它用到循環(huán)里
for i in soup.find_all('a'): print(i)
這樣就依次輸出了所有的 標簽
Part2
我們已經(jīng)得到了所有 標簽的內(nèi)容,但一個問題擺在我們面前,并不是所有的這樣的標簽都是我們所需要的
那么如何從中進行篩選,請先根據(jù)示例完成,之后再來學習相關(guān)知識
for i in soup.find_all('a',attrs={"class":"mnav"}): print(i.string + ' ' + i.attrs['href'])
得到的輸出是這樣的:
新聞 http://news.baidu.comhao123 http://www.hao123.com地圖 http://map.baidu.com視頻 http://v.baidu.com貼吧 http://tieba.baidu.com
這樣就達到了這樣一個目的,從網(wǎng)頁中提取類為 mnav 的標簽,并輸出了標簽文字部分和 href 屬性內(nèi)容
舉一反三
請依據(jù)之前的內(nèi)容在此基礎(chǔ)上繼續(xù)完成:
*輸出所有
標簽中所包含的文字信息
完成后請使用 exit() 或 Ctrl+D 退出 Python 命令行
Part3
有了前面的內(nèi)容,讓我們了解一下 Beautiful Soup 的一些基本元素
Name
標簽的名字,
…
的Name是 'p', .name
Attributes
標簽的屬性,字典形式組織,.attrs
你可以用如同上面的例子一樣操作字典的方式來操作標簽的屬性
NavigableString
標簽內(nèi)非屬性字符串,.string
.text 也能起到類似效果
Comment
標簽內(nèi)字符串的注釋部分,一種特殊的Comment類型,可以處理 中的數(shù)據(jù)
Part4(選)
本部分介紹標簽遍歷方法,需要你對數(shù)圖有一定了解,如果你覺得這一部分難以理解,可以暫時忽略
你可以在學習數(shù)據(jù)結(jié)構(gòu)相關(guān)知識后再進行學習,在此之前,你可以通過 find_all 全遍歷再配合條件判斷能實現(xiàn)相同的功能
下行遍歷
.contents 子節(jié)點的列表,將 所有子節(jié)點存入列表
.children 子節(jié)點的迭代類型,與 .contents 類似,用于循環(huán)遍歷子節(jié)點
.descendants 子孫節(jié)點的迭代類型,包含所有子孫節(jié)點,用于循環(huán)遍歷
上行遍歷
.parent 父節(jié)點
.parents 父節(jié)點標簽迭代,用于循環(huán)遍歷父節(jié)點
平行遍歷
.next_sibling 返回按照 HTML 文本順序的下一個平行節(jié)點標簽
.next_siblings 迭代類型,返回按照 HTML 文本順序的后續(xù)所有平行節(jié)點標簽
.previous_sibling 返回按照 HTML 文本順序的上一個平行節(jié)點標簽
.previous_siblings 迭代類型,返回按照 HTML 文本順序的前續(xù)所有平行節(jié)點標簽
值得注意的一些事
注意:bs4 庫將任何 HTML 輸入都變成 utf‐8 編碼
當你在實際爬取頁面過程中,編碼往往不總是 utf-8, 對于編碼的處理就非常關(guān)鍵
建議如果您對編碼處理了解的并不全面,可以再次復習Python編碼解碼部分內(nèi)容。
在解決遇到的問題過程中進行學習也是很有效的
爬蟲實戰(zhàn):云+社區(qū)專欄文章
實戰(zhàn)要求
在這一部分教程會給出一定的提示,請嘗試自行完成,如果有很難理解的地方,可以參考示例代碼
為了方便多次修改與調(diào)試,你可以在用戶目錄下,創(chuàng)建并打開task2.py 在其中編寫(注意使用 Python3 環(huán)境運行),當然也可以直接在Python命令行
提示:
文章標題位于 com-article-panel-title 類的
標簽下的 標簽里
標簽的使用可以嵌套,如你可以使用類似 soup.h3.a 這樣的方式選擇在
標簽里的 標簽
參考代碼
示例代碼:/home/ubuntu/task2.py
import requestsfrom bs4 import BeautifulSoupurl="https://cloud.tencent.com/developer/column/2061"res=requests.get(url)res.encoding=res.apparent_encodingsoup=BeautifulSoup(res.text,'html.parser')for h3 in soup.find_all('h3',attrs={"class":"com-article-panel-title"}): print("https://cloud.tencent.com" + h3.a.attrs['href']) print(h3.a.string,end="\n\n")
Python 爬蟲未完待續(xù)
簡要回顧
至此,你已經(jīng)有了爬取一個網(wǎng)頁并從中提取信息的能力,利用 Python 爬蟲能給我們帶來很多便利
再次我需要再次提醒正在實驗的各位,爬蟲有利有弊,很多網(wǎng)站所有者并不喜歡爬蟲,爬蟲也會給網(wǎng)站帶來運維壓力
如果涉及到企業(yè)數(shù)據(jù)、隱私相關(guān)信息,無限制的爬取甚至需要承擔一定的責任
同時請不要在非學習交流為目的情況下爬取網(wǎng)站 robots 協(xié)議所禁止爬取的內(nèi)容
當我們完成了這些,還有一些問題困擾著我們
Beautiful Soup 庫能方便的處理網(wǎng)頁標簽
但是 HTML 是很寬松的語言,經(jīng)常會發(fā)現(xiàn)網(wǎng)頁并不嚴格按照標簽的規(guī)范來完成,或者你想要的信息所在的標簽沒有簡單的定位方式
你所知道的只有你所需要信息的格式,那么該怎么辦?
這時候就需要我們配合正則表達式庫來完成我們的任務(wù)了
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。