選擇器bs4進行數據解析:
- 數據解析的原理:首先進行標簽定位,然后進行提取標簽以及標簽屬性中存儲的數據
- bs4數據解析的原理:首先實例化一個BeautifulSoup對象,並將頁面源碼數據加載到該對象中,然后通過調用BeautifulSoup對象中相關的屬性和方法進行標簽定位和數據提取
- 環境安裝:bs4與lxml
- 實例化BeautifulSoup對象:
1、導包:from bs4 import BeautifulSoup
2、對象的實例化,有兩種方法:
方法一:將本地的html文檔中的數據加載到該對象中
fp = open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml') # 參數二是固定的,參數一是本地的html的文件指針fp
方法二:將互聯網上獲取的源碼頁面加載到該對象中
page_text = response.text
soup = BeautifulSoup(page_text,'lxml')
3、提供的用於數據解析的方法和屬性:
soup.tagName(標簽名):返回的是文檔中第一次出現的tagName對應的標簽
soup.find():返回一個單數,只能找到符合要求的第一個標簽的內容
(1)find('tagName'):等同於soup.tagName
(2)屬性定位:soup.find('tagName',屬性名='屬性值') ------------------------------------------------------------- 【若屬性名為特殊的class等,加個下划線即可】
soup.find_all('tagName'):返回一個復數(列表),可以找到符合要求的所有標簽內容
soup.select():
soup.select('某種選擇器(id、class、標簽等)'),返回一個列表 ------------------------------------------------------------- 【類選擇器寫法 .value值】
層級選擇器soup.select('選擇器1 > 選擇器2 > 選擇器3')[Num]: > 表示一個層級,因為返回的是一個列表,所以用[Num]表示選取列表中的第Num個內容
層級選擇器soup.select('選擇器1 > 選擇器2 選擇器3'):空格表示多個層級
4、獲取標簽之間的文本數據:
在定位到某個標簽后,還需要獲取,比如:soup.a.text、soup.a.string、soup.a.get_text()
區別:.text與.get_text()可以獲取某一標簽中所有的文本內容;.string只可以獲取該標簽下直系的文本內容
5、獲取標簽中的屬性值:
soup.a['屬性名稱']
- 實際案例:爬取某小說的標題與章節內容
首先,對首頁數據進行爬取,按照之前的代碼會存在抓取到的數據亂碼的問題,於是對代碼進行了改進:
# 對首頁頁面數據進行爬取 url = 'https://www.shicimingju.com/book/sanguoyanyi.html' # 解決標題亂碼 html = requests.get(url=url,headers=headers) html.encoding = 'utf-8' page_text = html.text
然后通過分析可知,我們要找的章節標題和詳情頁的超鏈,在class為book_mulu的div中:
那么就可以開始編寫代碼了,通過select解析,初步解析出一個存放<li>標簽內容的列表,然后對該列表進行遍歷,每次要通過string獲取單個<li>標簽中的<a>標簽的內容,即為標題;再獲取標簽屬性值href,即為每章節詳情頁的url,接下來模擬對每章詳情頁發送請求,然后解析出小說正文內容,最后獲取到並進行持久化存儲,over!!!
for li in li_list: # 獲取li標簽中的a標簽的數據,因為string只能獲取直系數據 title = li.a.string detail_url = 'https://www.shicimingju.com/' + li.a['href'] # 對詳情頁發起請求,解析出章節內容 # 解決文本亂碼 html_detail = requests.get(url=detail_url,headers=headers) html_detail.encoding = 'utf-8' detail_page_text = html_detail.text # 解析出詳情頁中的章節內容 detail_soup = BeautifulSoup(detail_page_text,'lxml') div_tag = detail_soup.find('div',class_='chapter_content') # 獲取章節內容 content = div_tag.text # 持久化存儲 fp.write(title + ':' + content + '\n') print(title,'爬取成功!!!')