爬蟲系列 | 六、詳解爬蟲中BeautifulSoup4的用法

bs4,全稱BeautifulSoup 4 , 它是Python獨有的一種解析方式。也就是說只有Python語言才能夠經過這種方式去解析數據。css

BeautifulSoup 3 只支持Python2,因此已經被淘汰了。

官網的介紹是這樣的html

Beautiful Soup 提供一些簡單的、python 式的函數用來處理導航、搜索、修改分析樹等功能。它是一個工具箱,經過解析文檔爲用戶提供須要抓取的數據,由於簡單,因此不須要多少代碼就能夠寫出一個完整的應用程序。 Beautiful Soup 自動將輸入文檔轉換爲 Unicode 編碼,輸出文檔轉換爲 utf-8 編碼。你不須要考慮編碼方式,除非文檔沒有指定一個編碼方式,這時,Beautiful Soup 就不能自動識別編碼方式了。而後,你僅僅須要說明一下原始編碼方式就能夠了。 Beautiful Soup 已成爲和 lxml、html6lib 同樣出色的 python 解釋器,爲用戶靈活地提供不一樣的解析策略或強勁的速度。

看起來很複雜,我用本身的理解,通俗的解釋一下python

咱們知道一個網頁的源代碼,是由多個標籤組成,好比<html>、<div>、<td>、<span>等等組成的,而bs4就是用來幫咱們精肯定位標籤位置,從而獲取標籤或者標籤屬性中內容的工具。bs4默認自帶的解析器,可是官方推薦的是更強大 速度更快的 lxml解析器網絡

其餘解析器的優缺點

1561447662879877.png

1、bs4的安裝

pip install bs4
pip install lxml

使用bs4解析時,推薦使用lxml解析器。這個在用xpath解析的時候也會用到函數

2、bs4解析原理

  • 首先實例化一個BeautifulSoup對象,而且將頁面源代碼加載到這個對象裏
  • 調用BeautifulSoup對象中的相關屬性或者方法進行標籤訂位和數據提取
一、如何實例化BeautifuSoup對象
a. 導入bs4包
from bs4 import BeautifulSoup
b.實例化對象

網頁源代碼,又分爲本地已經持久化的HTML文件和網絡上直接獲取的源代碼。工具

若是是本地已經持久化的文件,能夠經過下面的方式將源代碼加載到bs4對象中測試

fp = open('xxx.html', 'r', encoding='utf-8')
# lxml:解析器
soup = BeautifulSoup(fp, 'lxml')

若是是經過requests庫獲取的網頁源代碼,經過下面的方式進行加載網站

response = requests.get(url)
html = response.text
soup = BeautifulSoup(html, 'lxml')

c.數據解析的方法和屬性this

bs4可以將複雜的HTML轉換成一個樹形結構,每一個節點都是Python對象。編碼

soup.tagName(標籤名): 返回的是文檔中第一次出現tagName對應的標籤及其相應內容

soup.tageName1.tageName2:返回tag1中tage2的標籤及其內容

soup.find:等同於soup.tagName,返回第一個匹配到的對象

soup.find_all:返回全部的匹配到的對象。

經過查看源碼會發現,find的本質其實就是調用了find_all, 而後返回第一個元素

參數解釋:

  • name :要查找的標籤名(字符串、正則、方法、True)
  • attrs: 標籤的屬性
  • recursive: 遞歸
  • text: 查找文本
  • **kwargs :其它 鍵值參數
def find(self, name=None, attrs={}, recursive=True, text=None,
             **kwargs):
        """Return only the first child of this Tag matching the given
        criteria."""
        r = None
        l = self.find_all(name, attrs, recursive, text, 1, **kwargs)
        if l:
            r = l[0]
        return r

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iXUox6yw-1611066850753)(C:UsersAdministratorAppDataRoamingTyporatypora-user-imagesimage-20210103164834540.png)]

上圖是我從某網站截取的部分畫面,翻譯成HTML以下(只保留了對本次分析有用的部分,爲了方便閱讀刪除了地址的域名信息)

<html>
 <head><titel>測試Title</titel></head>
 <body>
  <div class="test">
      <ul>
          <li> <a href="zhaosi.html">![](123456789.jpg)<p>尼古拉斯趙四</p></a> </li>
      </ul>
  </div>
  <div class="nr_zt w1180">
   <ul>
    <li> <a id="star" href="zhengshuang.html">![](5940f2cd6b759.jpg)<p>鄭爽</p></a> </li>
    <li> <a id="star" href="zhuyilong.html">![](5b56e0fabf5bf.jpg)<p>朱一龍</p></a> </li>
    <li> <a id="star" href="zhoudongyu.html">![](5a28b93be8155.jpg)<p>周冬雨</p></a> </li>
    <li> <a id="star" href="huyitian_1.html">![](5aa36dfbe5f61.jpg)<p>胡一天</p></a> </li>
    <li> <a id="star" href="yiyangqianxi.html">![](5a28d243b0382.jpg)<p>易烊千璽</p></a> </li>
    <li> <a id="star" href="dilireba.html">![](5a28b69334087.jpg)<p>迪麗熱巴</p></a> </li>
   </ul>
  </div>
 </body>
</html>

看下面幾個例子

# 獲取第一個li標籤
# <li> <a href="http://www.win4000.com/mt/zhengshuang.html">![](http://pic1.win4000.com/tj/2017-06-14/5940f2cd6b759.jpg)<p>鄭爽</p></a> </li>
print(soup.li)
# # 獲取第一個li標籤中a標籤
# <a href="http://www.win4000.com/mt/zhengshuang.html">![](http://pic1.win4000.com/tj/2017-06-14/5940f2cd6b759.jpg)<p>鄭爽</p></a>
print(soup.li.a)
#獲取第一個li標籤中a標籤
print(soup.find('li').a)
# 獲取全部li標籤
print(soup.find_all('li'))
# 獲取title標籤
print(soup.title)
# 獲取a標籤的父級標籤
print(soup.a.parent)
# 獲取a標籤的父級標籤的名字
print(soup.a.parent.name)

如何獲取HTML中的href?

分析:href是a標籤中的一個屬性,而a標籤又在li標籤中

在bs4中提取標籤中的屬性能夠經過attrs來獲取

from bs4 import BeautifulSoup

fp = open('baidu.html', 'r', encoding='utf-8')
soup = BeautifulSoup(fp, 'lxml')

# 若是獲取一個能夠這樣寫
result = soup.a.attrs['href']
# zhaosi.html
print(result)

# 獲取所有,可經過先獲取a標籤 而後遍歷獲取
all_result = soup.find_all('a')
for i in all_result:
    print(i.attrs['href'])

print("* " * 40)
#  若是我只想獲取id = star的href,須要先對id進行篩選
# 返回全部包含id=star的a標籤
star_result = soup.find_all('a', id='star')
for i in star_result:
    print(i.attrs['href'])

# 返回包含id的標籤(只要有id屬性,而且有值的標籤都返回)
soup.find_all(id=True)

# 假設尼古拉斯趙四 不是第一個a標籤中的內容.提取對應的href
# 須要先定位class=‘test’對應div的位置
# 方法一:
result = soup.find('div', 'test')
print(result.a['href'])

# 方法二(class爲python中關鍵字,所以查找html中的class屬性須要添加個下劃線 class_)
result1 = soup.find('div', class_='test')
print(result1.a['href'])

# 方法三
result2 = soup.find('div', attrs={'class': 'test'})

# 獲取第一個a標籤中的文本內容
print(soup.a.text)

a_result = soup.find_all('a')
for i in a_result:
    # 生成的是一個迭代器
    print(i.strings)
    print(list(i.strings))
    print(i.string)
    print(i.text)

其餘補充

# 返回子孫節點
# children返回迭代器
result = soup.a.children
for i in result:
    print(i)

# 返回子孫節點, contents返回列表
r = soup.a.contents
print(r)

# 能夠經過正則對某個屬性進行匹配
# 好比返回href中以zh開頭的標籤
import re
reg = re.compile('^zh')
result = soup.find_all(href=reg)
print(result)

選擇器

bs4很是強大,還支持css選擇器。經過select來完成

<html>
 <head><titel>測試Title</titel></head>
 <body>
  <div class="test">
      <ul>
          <li> <a href="zhaosi.html">![](123456789.jpg)<p>尼古拉斯趙四</p></a> </li>
      </ul>
  </div>
  <div class="nr_zt w1180">
   <ul>
    <li> <a id="star" href="zhengshuang.html">![](5940f2cd6b759.jpg)<p>鄭爽</p></a> </li>
    <li> <a id="star" href="zhuyilong.html">![](5b56e0fabf5bf.jpg)<p>朱一龍</p></a> </li>
    <li> <a id="star" href="zhoudongyu.html">![](5a28b93be8155.jpg)<p>周冬雨</p></a> </li>
    <li> <a id="star" href="huyitian_1.html">![](5aa36dfbe5f61.jpg)<p>胡一天</p></a> </li>
    <li> <a id="star" href="yiyangqianxi.html">![](5a28d243b0382.jpg)<p>易烊千璽</p></a> </li>
    <li> <a id="star" href="dilireba.html">![](5a28b69334087.jpg)<p>迪麗熱巴</p></a> </li>
   </ul>
  </div>
 </body>
</html>
from bs4 import BeautifulSoup

fp = open('baidu.html', 'r', encoding='utf-8')
soup = BeautifulSoup(fp, 'lxml')

# 返回一個全部a標籤的列表
result = soup.select('a')
# 返回第一個
result1 = soup.select('a')[0]

"""
class選擇器 : .className
"""
# 一層一層的進行選擇,用 > 鏈接  即 > : 表示一個層級
# 輸出 class = nr_zt 下ul下的li下的a標籤集合
a = soup.select('.nr_zt > ul > li > a')
# 多個層級關聯,使用 空格。
# 輸出 class= 'nr_zt' 下的a標籤集合
b = soup.select('.nr_zt a')


"""
id選擇器: # idName
"""
result = soup.select('#star')

# 經過href屬性查找,返回列表
soup.select('a[href="zhengshuang.html"]')

# 獲取對應標籤中img標籤的src值
a = soup.select('a[href="zhengshuang.html"]')[0]
print(a.img['src']) # 5940f2cd6b759.jpg

以上就是bs4的經常使用操做代碼,實際上在具體的爬蟲過程當中,匹配的方式比較靈活,因此你們也不用能夠的去背,只須要記住其原理便可。

在這裏插入圖片描述

相關文章
相關標籤/搜索