python爬蟲Beautiful Soup基礎知識總結(附帶實操案例)

python爬蟲之Beautiful Soup基礎知識

Beautiful Soup是一個能夠從HTML或XML文件中提取數據的python庫。它能同過你喜歡的轉換器實現慣用的文檔導航,查找,修改文檔的方式。css

須要注意的是,Beautiful Soup已經自動將輸入文檔轉換爲Unicode編碼,輸出文檔轉換爲utf-8編碼。所以在使用它的時候不須要考慮編碼方式,僅僅須要說明一下原始編碼方式就能夠了。html

1、安裝Beautiful Soup庫

使用pip命令工具安裝Beautiful Soup4庫python

pip install beautifulsoup4

點擊獲取Python學習資料正則表達式

2、BeautifulSoup庫的主要解析器

具體操做:app

html = 'https://www.baidu.com'
bs = BeautifulSoup(html, 'html.parser')

3、BeautifulSoup的簡單使用

提取百度搜索頁面的部分源代碼爲例:python爬蟲

<!DOCTYPE html>
<html>
<head>
  <meta content="text/html;charset=utf-8" http-equiv="content-type" />
  <meta content="IE=Edge" http-equiv="X-UA-Compatible" />
  <meta content="always" name="referrer" />
  <link
href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.
css" rel="stylesheet" type="text/css" />
  <title>百度一下,你就知道 </title>
</head>
<body link="#0000cc">
 <div id="wrapper">
  <div id="head">
    <div class="head_wrapper">
     <div id="u1">
      <a class="mnav" href="http://news.baidu.com" name="tj_trnews">新聞
</a>
      <a class="mnav" href="https://www.hao123.com"
name="tj_trhao123">hao123 </a>
      <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地圖 </a>
      <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">視頻 </a>
      <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">貼吧
</a>
      <a class="bri" href="//www.baidu.com/more/" name="tj_briicon"
style="display: block;">更多產品 </a>
     </div>
    </div>
  </div>
 </div>
</body>
</html>

綜合requests和使用BeautifulSoup庫的html解析器,對其進行解析以下:ide

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text

bs = BeautifulSoup(html, 'html.parser')

print(bs.prettify())    # prettify 方式輸出頁面

結果以下:函數

<!DOCTYPE html>
<!--STATUS OK-->
<html>
 <head>
  <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
  <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
  <meta content="always" name="referrer"/>
  <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
  <title>
   百度一下,你就知道
  </title>
 </head>
 <body link="#0000cc">
  <div id="wrapper">
   <div id="head">
    <div class="head_wrapper">
     <div class="s_form">
      <div class="s_form_wrapper">
       <div id="lg">
        <img height="129" hidefocus="true" src="//www.baidu.com/img/bd_logo1.png" width="270"/>
       </div>
       <form action="//www.baidu.com/s" class="fm" id="form" name="f">
        <input name="bdorz_come" type="hidden" value="1"/>
        <input name="ie" type="hidden" value="utf-8"/>
        <input name="f" type="hidden" value="8"/>
        <input name="rsv_bp" type="hidden" value="1"/>
        <input name="rsv_idx" type="hidden" value="1"/>
        <input name="tn" type="hidden" value="baidu"/>
        <span class="bg s_ipt_wr">
         <input autocomplete="off" autofocus="autofocus" class="s_ipt" id="kw" maxlength="255" name="wd" value=""/>
        </span>
        <span class="bg s_btn_wr">
         <input autofocus="" class="bg s_btn" id="su" type="submit" value="百度一下"/>
        </span>
       </form>
      </div>
     </div>
     <div id="u1">
      <a class="mnav" href="http://news.baidu.com" name="tj_trnews">
       新聞
      </a>
      <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">
       hao123
      </a>
      <a class="mnav" href="http://map.baidu.com" name="tj_trmap">
       地圖
      </a>
      <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">
       視頻
      </a>
      <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">
       貼吧
      </a>
      <noscript>
       <a class="lb" href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1" name="tj_login">
        登陸
       </a>
      </noscript>
      <script>
       document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登陸</a>');
      </script>
      <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">
       更多產品
      </a>
     </div>
    </div>
   </div>
   <div id="ftCon">
    <div id="ftConw">
     <p id="lh">
      <a href="http://home.baidu.com">
       關於百度
      </a>
      <a href="http://ir.baidu.com">
       About Baidu
      </a>
     </p>
     <p id="cp">
      ©2017 Baidu
      <a href="http://www.baidu.com/duty/">
       使用百度前必讀
      </a>
      <a class="cp-feedback" href="http://jianyi.baidu.com/">
       意見反饋
      </a>
      京ICP證030173號
      <img src="//www.baidu.com/img/gs.gif"/>
     </p>
    </div>
   </div>
  </div>
 </body>
</html>

4、BeautifulSoup類的基本元素

BeautifulSoup將複製的HTML文檔轉換成一個複雜的樹型結構,每一個節點都是python對象,全部對象能夠概括爲四種 Tag,NavigableString,Comment,Beautifulsoup 。工具

Tag

任何存在於HTML語法中的標籤均可以bs.tag訪問得到,若是在HTML文檔中存在多個相同的tag對應的內容時,bs.tag返回第一個。示例代碼以下:學習

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')
# 獲取第一個a標籤的全部內容
print(bs.a)	# <a class="mnav" href="http://news.baidu.com" name="tj_trnews">新聞</a>
print(type(bs.a))	# <class 'bs4.element.Tag'>

在Tag標籤中最重要的就是html頁面中的nam和attrs屬性,使用方法以下:

print(bs.a.name)    # a
# 把a標籤的全部屬性打印輸出出來,返回一個字典類型
print(bs.a.attrs)   # {'href': 'http://news.baidu.com', 'name': 'tj_trnews', 'class': ['mnav']}
# 等價 bs.a.get('class')
print(bs.a['class'])    # ['mnav']
bs.a['class'] = 'newClass'  # 對class屬性的值進行修改
print(bs.a) # <a class="newClass" href="http://news.baidu.com" name="tj_trnews">新聞</a>
del bs.a['class']   # 刪除class屬性
print(bs.a) # <a href="http://news.baidu.com" name="tj_trnews">新聞</a>

NavigableString

NavigableString中的string方法用於獲取標籤內部的文字,代碼以下:

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

print(bs.title.string)  # 百度一下,你就知道
print(type(bs.title.string))    # <class 'bs4.element.NavigableString'>

Comment

Comment對象是一個特殊類型的NavigableString對象,其輸出的內容不包括註釋符號,用於輸出註釋的內容。

from bs4 import BeautifulSoup

html = """<a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!--新聞--></a>"""
bs = BeautifulSoup(html, 'html.parser')

print(bs.a.string)  # 新聞
print(type(bs.a.string))    # <class 'bs4.element.Comment'>

BeautifulSoup

bs對象表示的是一個文檔的所有內容,大部分時候,能夠把它看成Tag對象,支持遍歷文檔樹和搜索文檔中描述的大部分方法。

由於Beautifulsoup對象並非真正的HTML或者XML的tag,因此它沒有name和attribute屬性。因此BeautifulSoup對象通常包含值爲"[document]"的特殊屬性.name

print(bs.name)	# [document]

5、基於bs4庫的HTML內容的遍歷方法

在HTML中有以下特定的基本格式,也是構成HTML頁面的基本組成成分。

而在這種基本的格式下有三種基本的遍歷流程

  • 下行遍歷
  • 上行遍歷
  • 平行遍歷

三種遍歷方式分別是從當前節點出發,對之上、之下、平行的格式以及關係進行遍歷。

下行遍歷

下行遍歷分別有三種遍歷屬性,以下所示:

代碼以下:

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

# 循環遍歷兒子節點
for child in bs.body.children:
    print(child)

# 循環遍歷子孫節點
for child in bs.body.descendants:
    print(child)

# 輸出子節點,以列表的形式
print(bs.head.contents)
print(bs.head.contents[0])  # 用列表索引來獲取它的某一個元素

上行遍歷

上行遍歷有兩種方式,以下所示:

代碼以下:

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

for parent in bs.a.parents:
    if parent is not None:
        print(parent.name)

print(bs.a.parent.name)

平行遍歷

平行遍歷有四種屬性,以下所示:

代碼以下:

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

for sibling in bs.a.next_siblings:
    print(sibling)

for sibling in bs.a.previous_siblings:
    print(sibling)

其它遍歷

6、文件樹搜索

使用bs.find_all(name, attires, recursive, string, **kwargs)方法,用於返回一個列表類型,存儲查找的結果。

name參數

若是是 指定的字符串 :會查找與字符串徹底匹配的內容,代碼以下:

a_list = bs.find_all("a")
print(a_list)

使用正則表達式:將會使用BeautifulSoup4中的search()方法來匹配,代碼以下:

import requests
from bs4 import BeautifulSoup
import re

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

t_list = bs.find_all(re.compile("p"))
for item in t_list:
    print(item)

傳入一個列表:Beautifulsoup4將會與列表中的任一元素匹配到的節點返回,代碼以下:

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

t_list = bs.find_all(["meta", "link"])
for item in t_list:
    print(item)

傳入一個函數或方法:將會根據函數或者方法來匹配,代碼以下:

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')


def name_is_exists(tag):
    return tag.has_attr("name")


t_list = bs.find_all(name_is_exists)
for item in t_list:
    print(item)

attrs參數

並非全部的屬性均可以使用上面這種方法進行搜索,好比HTML的data屬性,用於指定屬性搜索。

import requests
from bs4 import BeautifulSoup

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

t_list = bs.find_all(attrs={"class": "mnav"})


for item in t_list:
    print(item)

string參數

經過string參數能夠搜索文檔中的字符串內容,與name參數的可選值同樣,string參數接受字符串,正則表達式,列表。

import requests
from bs4 import BeautifulSoup
import re

# 使用requests庫加載頁面代碼
r = requests.get('https://www.baidu.com')
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

t_list = bs.find_all(attrs={"class": "mnav"})
for item in t_list:
    print(item)

# text用於搜索字符串
t_list = bs.find_all(text="hao123")
for item in t_list:
    print(item)

# text能夠通其它參數混合使用用來過濾tag
t_list = bs.find_all("a", text=["hao123", "地圖", "貼吧"])
for item in t_list:
    print(item)

t_list = bs.find_all(text=re.compile("\d\d"))
for item in t_list:
    print(item)

使用find_all()方法,經常使用到的正則表達式形式 import re 代碼以下:

bs.find_all(string = re.compile('python'))	# 指定查找內容

# 或者指定使用正則表達式要搜索的內容
string = re.compile('python')	# 字符爲python
bs.find_all(string)	# 調用方法模版

7、經常使用的find()方法以下

8、爬取京東電腦數據

爬取的例子直接輸出到屏幕。

(1)要爬取京東一頁的電腦商品信息,下圖所示:

(2)咱們的目的是須要獲取京東這一個頁面上全部的電腦數據,包括價格,名稱,ID等。具體代碼以下:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import requests
from bs4 import BeautifulSoup

headers = {
        'User-agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/66.0.3359.139 Safari/537.36"
    }

URL = "https://search.jd.com/search?keyword=macbook%20pro&qrst=1&suggest=5.def.0.V09&wq=macbook%20pro"

r = requests.get(URL, headers=headers)
r.encoding = r.apparent_encoding
html = r.text
bs = BeautifulSoup(html, 'html.parser')

all_items = bs.find_all('li', attrs={"class": "gl-item"})

for item in all_items:
    computer_id = item["data-sku"]
    computer_name = item.find('div', attrs={'class': 'p-name p-name-type-2'})
    computer_price = item.find('div', attrs={'class': 'p-price'})
    print('電腦ID爲:' + computer_id)
    print('電腦名稱爲:' + computer_name.em.text)
    print('電腦價格爲:' + computer_price.find('i').string)
    print('------------------------------------------------------------')

部分結果以下圖所示:

點擊獲取Python學習資料

相關文章
相關標籤/搜索