python爬蟲之BeautifulSoup

BeautifulSoup

一個靈活又方便的網頁解析庫,處理高效,支持多種解析器。利用它就不用編寫正則表達式也能方便的實現網頁信息的抓取。html

Beautiful Soup支持多種解析器, Python有默認的解析器,推薦安裝lxml 解析器,效率高,速度快。前端

用法

from bs4 import BeautifulSoup

html = '''
<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>
'''
soup = BeautifulSoup(html,'lxml')
print(soup.prettify())
print(soup.title)
print(soup.title.name)
print(soup.title.string)
print(soup.title.parent.name)
print(soup.p)
print(soup.p["class"])
print(soup.a)
print(soup.find_all('a'))
print(soup.find(id='link3'))

標籤選擇器

print(soup.title)
print(soup.head)
print(soup.p)python

經過這種soup.標籤名 咱們就能夠得到這個標籤的內容
這裏有個問題須要注意,經過這種方式獲取標籤,若是文檔中有多個這樣的標籤,返回的結果是第一個標籤的內容,如上面咱們經過soup.p獲取p標籤,而文檔中有多個p標籤,可是隻返回了第一個p標籤內容正則表達式

獲取名稱

當咱們經過soup.title.name的時候就能夠得到該title標籤的名稱,即titlespa

獲取屬性

print(soup.p.attrs['name'])
print(soup.p['name'])
上面兩種方式均可以獲取p標籤的name屬性值code

獲取內容

print(soup.p.string)
結果就能夠獲取第一個p標籤的內容:
The Dormouse's storyorm

嵌套選擇

咱們直接能夠經過下面嵌套的方式獲取xml

print(soup.head.title.string)htm

子節點

1.contents對象

print(soup.p.contents)

結果是將p標籤下的全部子標籤存入到了一個列表中

2.children

經過children和經過contents獲取的結果是同樣的,可是不一樣的地方是soup.p.children是一個迭代對象,而不是列表,只能經過循環的方式獲取素有的信息

print(soup.p.children)
for i,child in enumerate(soup.p.children):
    print(i,child)

子孫節點

descendants

print(soup.descendants)

同時這種獲取的結果也是一個迭代器

父節點和祖先節點

經過soup.a.parent就能夠獲取父節點的信息

經過list(enumerate(soup.a.parents))能夠獲取祖先節點,這個方法返回的結果是一個列表,會分別將a標籤的父節點的信息存放到列表中,以及父節點的父節點也放到列表中,而且最後還會講整個文檔放到列表中,全部列表的最後一個元素以及倒數第二個元素都是存的整個文檔的信息

兄弟節點

soup.a.next_siblings 獲取後面的兄弟節點
soup.a.previous_siblings 獲取前面的兄弟節點
soup.a.next_sibling 獲取下一個兄弟標籤
souo.a.previous_sinbling 獲取上一個兄弟標籤

標準選擇器

find

find(name,attrs,recursive,text,**kwargs)
find返回的匹配結果的第一個元素

find_all

find_all(name,attrs,recursive,text,**kwargs)
能夠根據標籤名,屬性,內容查找文檔,返回全部

1.name
html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all('ul'))
print(type(soup.find_all('ul')[0]))

同時咱們是能夠針對結果再次find_all,從而獲取全部的li標籤信息

for ul in soup.find_all('ul'):
    print(ul.find_all('li'))
2.attrs

attrs能夠傳入字典的方式來查找標籤,可是這裏有個特殊的就是class,由於class在python中是特殊的字段,因此若是想要查找class相關的能夠更改attrs={'class_':'element'}或者soup.find_all('',{"class":"element}),特殊的標籤屬性能夠不寫attrs,例如id

html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1" name="elements">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(attrs={'id': 'list-1'}))
print(soup.find_all(attrs={'name': 'elements'}))
3.text

結果返回的是查到的全部的text='Foo'的文本

html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.find_all(text='Foo'))

4.select

經過select()直接傳入CSS選擇器就能夠完成選擇
熟悉前端的人對CSS可能更加了解,其實用法也是同樣的
.表示class #表示id
標籤1,標籤2 找到全部的標籤1和標籤2
標籤1 標籤2 找到標籤1內部的全部的標籤2
[attr] 能夠經過這種方法找到具備某個屬性的全部標籤
[atrr=value] 例子[target=_blank]表示查找全部target=_blank的標籤

 

html='''
<div class="panel">
    <div class="panel-heading">
        <h4>Hello</h4>
    </div>
    <div class="panel-body">
        <ul class="list" id="list-1">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
            <li class="element">Jay</li>
        </ul>
        <ul class="list list-small" id="list-2">
            <li class="element">Foo</li>
            <li class="element">Bar</li>
        </ul>
    </div>
</div>
'''
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.select('.panel .panel-heading'))
print(soup.select('ul li'))
print(soup.select('#list-2 .element'))
print(type(soup.select('ul')[0]))

 

其餘一些相似的用法:
find_parents()返回全部祖先節點,find_parent()返回直接父節點。
find_next_siblings()返回後面全部兄弟節點,find_next_sibling()返回後面第一個兄弟節點。
find_previous_siblings()返回前面全部兄弟節點,find_previous_sibling()返回前面第一個兄弟節點。
find_all_next()返回節點後全部符合條件的節點, find_next()返回第一個符合條件的節點
find_all_previous()返回節點後全部符合條件的節點, find_previous()返回第一個符合條件的節點

內容獲取

1..string 用來獲取標籤的內容 

2.get_text() 用來獲取標籤中全部字符串包括子標籤的。

可是須要了解選擇器獲得的數據是什麼類型,find獲得的是<class 'bs4.element.Tag'> ,find_all獲得的是<class 'bs4.element.ResultSet'> 

1.<class 'bs4.element.ResultSet'>  這裏是字典外套了一個列表

2.<class 'bs4.element.Tag'> 直接爲一個字典

因此find_all獲得的內容須要先選擇列表索引,而後再按照字典去取值

相關文章
相關標籤/搜索