引入
大多數情況下的需求,我們都會指定去使用聚焦爬蟲,也就是爬取頁面中指定部分的數據值,而不是整個頁面的數據。因此,在聚焦爬蟲中使用數據解析。所以,我們的數據爬取的流程為:
- 指定url
- 基於requests模塊發起請求
- 獲取響應中的數據
- 數據解析
- 進行持久化存儲
數據解析:
- 被應用在聚焦爬蟲。
- 解析的數據存儲在標簽之間或者標簽對應的屬性中
BeautifulSoup解析
環境安裝
需要將pip源設置為國內源,阿里源、豆瓣源、網易源等
- windows
- (1)打開文件資源管理器(文件夾地址欄中)
- (2)地址欄上面輸入 %appdata%
- (3)在這里面新建一個文件夾 pip
- (4)在pip文件夾里面新建一個文件叫做 pip.ini ,內容寫如下即可
[global] timeout = 6000 index-url = https://mirrors.aliyun.com/pypi/simple/ trusted-host = mirrors.aliyun.com
- linux
- (1)cd ~
- (2)mkdir ~/.pip
- (3)vi ~/.pip/pip.conf
- (4)編輯內容,和windows一模一樣
- 需要安裝:pip install bs4
bs4在使用時候需要一個第三方庫,把這個庫也安裝一下
pip install lxml
- 環境安裝:
pip install lxml
pip install bs4
解析原理:
- 實例化一個BeautifuSoup對象,然后將頁面源碼數據加載到該對象中;
BeautifulSoup(fp,'lxml') BeautifulSoup(page_text,'lxml')
- 調用該對象相關屬性和方法進行標簽定位和數據提取;
使用流程:
- 導包:from bs4 import BeautifulSoup
- 使用方式:可以將一個html文檔,轉化為BeautifulSoup對象,然后通過對象的方法或者屬性去查找指定的節點內容
(1)轉化本地文件:
- soup = BeautifulSoup(open('本地文件'), 'lxml')
(2)轉化網絡文件:
- soup = BeautifulSoup('字符串類型或者字節類型', 'lxml')
(3)打印soup對象顯示內容為html文件中的內容。打印的是加載到該對象的源碼
from bs4 import BeautifulSoup fp = open('./test.html','r',encoding='utf-8') soup = BeautifulSoup(fp,'lxml') print(soup)
相關屬性和方法:
(1)根據標簽名查找
soup.tagName:定位到第一次出現的標簽,只能找到第一個符合要求的標簽
print(soup.div)
print(soup.p)
(2)獲取屬性
- soup.a.attrs 獲取a所有的屬性和屬性值,返回一個字典
- soup.a.attrs['href'] 獲取href屬性
- soup.a['href'] 也可簡寫為這種形式
print(soup.a['href'])
(3)獲取內容:直接將列表內容轉換成字符串,是單數的。不需要join了
- soup.a.string
- soup.a.text
- soup.a.get_text()
【注意】如果標簽里還有標簽,那么string獲取到的結果為None,而其它兩個,可以獲取文本內容
string: # 直系 text,get_text(): # 所有
print(soup.p.string)
print(soup.p.text)
print(soup.p.get_text)
(4)find:找到第一個符合要求的標簽,加第二個參數是屬性定位,如果是class屬性需要加一個下划線,否則會被認成關鍵字。其他的不需要。
soup.find('tagName',attrName="attrValue"):屬性定位。返回值是單數
- soup.find('a') 找到第一個符合要求的
- soup.find('a', title="xxx")
- soup.find('a', alt="xxx")
- soup.find('a', class_="xxx")
- soup.find('a', id="xxx")
print(soup.find('div',class_='song'))
(5)find_all:找到所有符合要求的標簽
- soup.find_all('a')
- soup.find_all(['a','b']) 找到所有的a和b標簽
- soup.find_all('a', limit=2) 限制前兩個
(6)根據選擇器選擇指定的內容。select選擇器返回永遠是列表,需要通過下標提取指定的對象
常見的選擇器:標簽選擇器(a)、類選擇器(.)、id選擇器(#)、層級選擇器
soup.select('#feng') print(soup.select('.song'))
層級選擇器:>表示一個層級,空格表示多個層級
層級選擇器是不可以用索引的,而最后返回的列表的基礎上是可以用索引的
print(soup.select('.tang li > a')[1])
print(soup.select('.song > a'))
案例
案例1:使用bs4實現將詩詞名句網站中三國演義小說的每一章的內容爬去到本地磁盤進行存儲
http://www.shicimingju.com/book/sanguoyanyi.html

import requests from bs4 import BeautifulSoup headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', } def parse_content(url): #獲取標題正文頁數據 page_text = requests.get(url,headers=headers).text soup = BeautifulSoup(page_text,'lxml') #解析獲得標簽 ele = soup.find('div',class_='chapter_content') content = ele.text #獲取標簽中的數據值 return content if __name__ == "__main__": url = 'http://www.shicimingju.com/book/sanguoyanyi.html' reponse = requests.get(url=url,headers=headers) page_text = reponse.text soup = BeautifulSoup(page_text,'lxml') #創建soup對象 a_eles = soup.select('.book-mulu > ul > li > a') #解析數據 print(a_eles) cap = 1 for ele in a_eles: print('開始下載第%d章節'%cap) cap+=1 title = ele.string content_url = 'http://www.shicimingju.com'+ele['href'] content = parse_content(content_url) with open('./sanguo.txt','w') as fp: fp.write(title+":"+content+'\n\n\n\n\n') print('結束下載第%d章節'%cap)
import requests from bs4 import BeautifulSoup headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36' } url = 'http://www.shicimingju.com/book/sanguoyanyi.html' page_text = requests.get(url=url,headers=headers).text #數據解析:章節標題,章節內容 soup = BeautifulSoup(page_text,'lxml') a_list = soup.select('.book-mulu > ul > li > a') fp = open('./sanguo.txt','w',encoding='utf-8') for a in a_list: #把a標簽當soup對象使用,因為它也是源碼 title = a.string detail_url = 'http://www.shicimingju.com'+a['href'] detail_page_text = requests.get(url=detail_url,headers=headers).text soup = BeautifulSoup(detail_page_text,'lxml') content = soup.find('div',class_="chapter_content").text # bs4中,把text提取出來的列表直接轉換成字符串,與xpath不同 fp.write(title+':'+content+'\n') print(title,'保存成功!') fp.close() print('over!')
a_list = soup.select('.book-mulu > ul > li > a') print(a_list) # 一個個a標簽
for a in a_list: #把a標簽當soup對象使用,因為它也是源碼 title = a.string # 章節標題 print(title)
for a in a_list: title = a.string detail_url = 'http://www.shicimingju.com'+a['href'] # 章節url print(detail_url)
for a in a_list: #把a標簽當soup對象使用,因為它也是源碼 title = a.string detail_url = 'http://www.shicimingju.com'+a['href'] detail_page_text = requests.get(url=detail_url,headers=headers).text soup = BeautifulSoup(detail_page_text,'lxml') content = soup.find('div',class_="chapter_content").text
最終生成文件
https://blog.csdn.net/qq_36381299/article/details/81000905