爬蟲解析庫beautifulsoup

1、介紹css

Beautiful Soup是一個能夠從HTML或XML文件中提取數據的python庫。html

#安裝Beautiful Soup
pip install beautifulsoup4

#安裝解析器
Beatiful Soup支持python標準庫中的HTML解析器,還支持一些第三方的解析器,其中一個是lxml,安裝lxml:
pip install lxml   #這個使用率最高的

另一個可供選擇的解析器是純python實現的html5lib,html5lib的解析方式與瀏覽器相同,安裝方式:
pip install html5lib

下表列出了主要的解析器,以及它們的優缺點,官網推薦使用lxml做爲解析器,由於效率更高. 在Python2.7.3以前的版本和Python3中3.2.2以前的版本,必須安裝lxml或html5lib, 由於那些Python版本的標準庫中內置的HTML解析方法不夠穩定.html5

解析器 使用方法 優點 劣勢
Python標準庫 BeautifulSoup(markup, "html.parser")
  • Python的內置標準庫
  • 執行速度適中
  • 文檔容錯能力強
  • Python 2.7.3 or 3.2.2)前 的版本中文檔容錯能力差
lxml HTML 解析器 BeautifulSoup(markup, "lxml")
  • 速度快
  • 文檔容錯能力強
  • 須要安裝C語言庫
lxml XML 解析器

BeautifulSoup(markup, ["lxml", "xml"])python

BeautifulSoup(markup, "xml")瀏覽器

  • 速度快
  • 惟一支持XML的解析器
  • 須要安裝C語言庫
html5lib BeautifulSoup(markup, "html5lib")
  • 最好的容錯性
  • 以瀏覽器的方式解析文檔
  • 生成HTML5格式的文檔
  • 速度慢
  • 不依賴外部擴展

2、基本使用app

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

#基本使用:容錯處理,文檔的容錯能力指的是在html代碼不完整的狀況下,使用該模塊能夠識別該錯誤。使用BeautifulSoup解析上述代碼,可以獲得一個 BeautifulSoup 的對象,並能按照標準的縮進格式的結構輸出
from bs4 import BeautifulSoup
soup=BeautifulSoup(html_doc,'lxml') #具備容錯功能
res=soup.prettify() #處理好縮進,結構化顯示
print(res)

3、遍歷文檔樹spa

遍歷文檔樹:即直接經過標籤名字選擇,特色是選擇速度快,但若是存在多個相同的標籤只返回第一個code

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

from bs4 import BeautifulSoup
soup=BeautifulSoup(html_doc,'lxml') #具備容錯功能
res=soup.prettify() #處理好縮進,結構化顯示

#1.用法
print(soup.p)   #存在多個相同的標籤只取出第一個p標籤
                      #<p class="title"><b>The Dormouse's story</b></p>
#2.獲取標籤的名稱
print(soup.p.name)    #p

#3.獲取標籤的屬性
print(soup.p.attrs)    #{'class': ['title']}   以字典形式打印

#4.獲取標籤的內容
print(soup.p.string)  #The Dormouse's story  #p下的文本只有一個時才能取到,不然爲None
print(soup.p.strings)  #拿到的是生成器對象,取到p下全部的文本內容
print(soup.p.text)  #取到p下全部的文本內容
for line in soup.stripped_strings:   #去掉空白
    print(line)   
#5.子節點、子孫節點
print(soup.p.contents)  #p下全部子節點 
                                  #[<b>The Dormouse's story</b>]

print(soup.p.children)  #獲得一個迭代器,包含p下全部的子節點   <list_iterator object at 0x00000054B207C780>
for i,child in enumerate(soup.p.children):   #循環取出
    print(i,child)    #0 <b>The Dormouse's story</b>


print(soup.p.descendants)  #獲取p下面全部的子孫節點   <generator object descendants at 0x00000054B203C258>
for i,child in enumerate(soup.p.descendants):  #文本也會顯示出來
    print(i,child)    #0 <b>The Dormouse's story</b>   1 The Dormouse's story
 
#6.父節點、祖先節點
print(soup.a.parent)  #獲取a標籤的父節點
print(soup.a.parents)  #找到a標籤全部的祖父節點,父親的父親。。。

4、搜索文檔樹orm

1.五種過濾器xml

搜索文檔樹:Beautiful Soup定義了不少搜索方法,這裏着重介紹2個:find()和find_all()

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

from bs4 import BeautifulSoup
soup=BeautifulSoup(html_doc,'lxml') 
res=soup.prettify() #處理好縮進,結構化顯示

#1.五種過濾器:字符串、正則、列表、True、方法
#1.1 字符串:即標籤名
print(soup.find_all('a'))  #寫標籤名,find_all找出全部a標籤

[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

#1.2 正則
import re
print(soup.find_all(re.compile('^b')))  #找到b開頭的標籤,結果有body和b標籤

#1.3列表:若是傳入列表參數,Beautiful Soup會將與列表中任一元素匹配的結果返回
print(soup.find_all(['a',['b']]))   #包含a和b標籤

[<b>The Dormouse's story</b>, <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

#1.4 True:能夠匹配任何值,下面代碼查到全部的tag,可是不會返回字符串節點
print(soup.find_all(True))   #返回全部標籤
for tag in soup.find_all(True):
    print(tag.name)   #返回全部節點:html/p/a/head...

#1.5方法:若是沒有合適的過濾器,能夠自定義一個方法,方法接受一個元素參數,若是方法返回True表示當前元素匹配成功,若是沒找到返回False
def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.attr('id')

print(soup.find_all(has_class_but_no_id))

2.find_all(name,attrs,recursive,text,**kwargs)   查詢全部

#2.1 name:搜索name參數的值能夠是任一類型的過濾器:字符串、正則、列表、True、方法
import re
print(soup.find_all(name=re.compile('^b')))  #這裏加不加name均可以

#2.2 keyword:   key=value的形式,value能夠是過濾器:字符串、正則、列表、True
print(soup.find_all(class_=re.compile('title')))   #[<p class="title"><b>The Dormouse's story</b></p>]   匹配class是title的標籤,注意類用class_
print(soup.find_all(id=True))  #查找有id屬性的標籤

#2.3按照類名查找,注意關鍵字是class_,class_=value,value能夠是五種選擇器之一
print(soup.find_all('a',class_='sister'))    #查找類爲sister的a標籤
print(soup.find_all('a',class_='sister sss'))    #查找類爲sister和sss的a標籤

#2.4 attrs
print(soup.find_all('p',attrs={'class':'story'}))   #查找class=story的p標籤

#2.5 text 值能夠是:字符串,列表,True,正則
print(soup.find_all(text='Elsie'))      #Elsie  文本
print(soup.find_all('a',text='Elsie'))  #獲取Elsie文本的a標籤

#2.6 limit參數:限制取值個數
print(soup.find_all('a',limit=2))   #取兩條a標籤

#2.7 recursive:
print(soup.find_all('a'))  #取出a標籤的
print(soup.find_all('a',recursive=False))  #取出a標籤的子節點  []

3.find(name,attrs,recursive,text,**kwargs)  查詢第一個符合條件的標籤

#3.find(name,attrs,recursive,text,**kwargs)
find_all() 方法將返回文檔中符合條件的全部tag,儘管有時候咱們只想獲得一個結果。好比文檔中只有一個a標籤,那麼能夠直接使用find()方法來查找。

惟一區別就是find_all()查詢到的結果返回的是包含元素的列表,而find()方法直接返回結果。 find_all()沒有找到符合元素返回空列表,find()方法找不到目標時返回None.

4.css選擇器  (******)使用select獲取

#使用select方法來查詢

#1.css選擇器
print(soup.select('.sister'))  #查詢class=sister的標籤

print(soup.select('#link1'))
print(soup.select('#link1')[0])
print(soup.select('#link1')[0].text)   #只要下面能夠取值就能夠一直. 下去

#2.獲取屬性
print(soup.select('#link2')[0].attrs)   #{'href': 'http://example.com/lacie', 'class': ['sister'], 'id': 'link2'}

#3.獲取內容
print(soup.select('#link1')[0].get_text())或者
print(soup.select('#link1')[0].text)

總結:

1.推薦使用lxml解析庫 2.講了三種選擇器:標籤選擇器,find和find_all,css選擇器
    1.標籤選擇器篩選功能弱,可是速度快
    2.建議使用find,find_all查詢匹配單個結果或者多個結果 3.若是對css選擇器很是熟悉建議使用select 3.獲取屬性attrs和獲取文本get_text()方法
相關文章
相關標籤/搜索