1.BeautifulSoup4概論
- 是不是覺得正則很麻煩呢?那么BeautifulSoup4(以下簡稱BS4)可以輕松解決這個問題。因為BS4不用寫正則??!
原理:將整個頁面轉為一個對象,然后將每個節點按照父子、兄弟的關系進行分類,最后形成一個樹狀結構。例如
<html>
<head></head>
<body>
<a>first</a>
<a>second</a>
</body>
</html>
經過解析后為
這樣子直接按需求取響應的對象就可以了。不需要正則進行匹配了。
2.流程
- 因為是對項目的重構。項目正則法傳送門
流程依舊是WWHS:
1.從哪爬 where
2.爬什么 what
3.怎么爬 how
4.爬了之后信息如何保存 save
3.具體代碼
- 使用pip安裝BS4.
- py文件頭部導入
import urllib.request
import chardet
from bs4 import BeautifulSoup
- 讀取網頁代碼
url="http://www.shicimingju.com/book/sanguoyanyi.html" # 要爬取的網絡地址
menuCode=urllib.request.urlopen(url).read() # 將網頁源代碼賦予menuCode
- 使用BS4處理后得到整個頁面的soup和要找的部分soup2。
soup=BeautifulSoup(menuCode,'html.parser') # 使用html解析器進行解析
menu=soup.find_all(id="mulu") # 在soup中找到id為mulu的節點
values = ','.join(str(v) for v in menu) # 將 menu轉換為str類型
soup2=BeautifulSoup(values,'html.parser');
soup2=soup2.ul # 用子節點代替soup2
- 找到書名并創建txt文件。
bookName=soup.h1.string # 找到了書名
f=open('D://'+bookName+'.txt','a',encoding='utf8')
- 爬取章節url,并解決url為本地的問題。
bookMenu=[] # 章節list
bookMenuUrl=[] # 章節url的list
for i in range(1,len(soup2.contents)-1): # 依次爬取書的章節
bookMenu.append(soup2.contents[i].string)
bookMenuUrl.append(soup2.contents[i].a['href'])
urlBegin="http://www.shicimingju.com" # 解決url為本地的問題
- 依次爬取每章內容并寫入txt。
for i in range (0,len(bookMenuUrl)):# 依次替換url,讀取每章頁面的內容
chapterCode=urllib.request.urlopen(urlBegin+bookMenuUrl[i]).read()
result=chardet.detect(chapterCode) # 檢驗讀取的頁面的編碼方式
if(result['confidence']>0.5): # 如果概率大于0.5 即采取這種編碼
chapterCode=chapterCode.decode(result['encoding'])
chapterSoup=BeautifulSoup(chapterCode,'html.parser') # 使用BS讀取解析網頁代碼
chapterResult=chapterSoup.find_all(id='con2') # 找到id=‘con2’的節點
chapterResult = ','.join(str(v) for v in chapterResult) # 將節點內的代碼轉為str類型
chapterSoup2=BeautifulSoup(chapterResult,'html.parser') # 使用BS解析節點內代碼
chapterSoup2=chapterSoup2.br
f.write(bookMenu[i]) # 寫入文件每章標題
for j in range(0,len(chapterSoup2)): # 循環寫入每章內容
chapterText=chapterSoup2.contents[j].string
f.write(chapterText)
4.總結
BeautifulSoup4將解析工作交給了框架本身,我們只用根據節點進行查詢就可以了。