1. 程式人生 > >Python學習筆記——pycharm 爬蟲:Beautiful soup

Python學習筆記——pycharm 爬蟲:Beautiful soup

昨天看了看Beautiful soup,看的我真的是一臉懵逼,lxml的全忘光了,兩個光混淆。很難受

一、安裝
安裝Beautiful soup 和 lxml庫

二、基本用法

# 資料來源
html = '''
    <html>
    <head>
    <title>The Dormouse`s story</title>
    <p class="story">
        Once upon a time there were three little sisters; and their names were
        <a href="http://exmple.com/elsie"
class="sister" id="link1"> <span>Elsie</span> </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> </p> <p class="story">...</p> ''' # 匯入庫
from bs4 import BeautifulSoup # 匯入資料來源 soup = BeautifulSoup(html) # 查詢資料並列印 # 補充格式並列印,會自動補全標籤, print(soup.prettify()) # 列印title標籤的內容 print(soup.title.string) # 列印title標籤的標籤名稱 print(soup.title.name)
<html>
 <head>
  <title>
   The Dormouse`s story
  </title>
 </head> #這裡添加了head的結束標籤
 <body
>
<p class="story"> Once upon a time there were three little sisters; and their names were <a class="sister" href="http://exmple.com/elsie" id="link1"> <span> Elsie </span> </a> <a class="sister" href="http://example.com/lacie" id="link2"> Lacie </a> and <a class="sister" href="http://example.com/tillie" id="link3"> Tillie </a> </p> <p class="story"> ... </p> </body> #這裡添加了body的結束標籤 </html> # 這裡添加了html的結束標籤

soup.prettify()補全了標籤,格式化了html片段

這裡寫圖片描述
soup.title.string和soup.title.name列印了文字和標籤名字

三、節點選擇器

# import lib
from bs4 import BeautifulSoup

# data source
這不重要 (滑稽)

# import data
soup = BeautifulSoup(html,'lxml')

# research and print
print(soup.)

1.選擇元素(節點)

# choice element title
print('title:',soup.title)

title: <title>The Dormouse`s story</title>
列印的是整個節點資訊

# the type of title
print('type of title:', type(soup.title))

type of title: <class 'bs4.element.Tag'>
節點是型別是tag型別

2.提取節點資訊

  • 獲得節點名稱

    soup.title.name
    
  • 獲得節點內容

    print(type(soup.title.string))
    print(soup.title.text)
    print(type(soup.title.text))
    print(soup.title.get_text())
    print(type(soup.title.get_text()))
    print(soup.title.getText())
    print(type(soup.title.getText()))
    
    The Dormouse`s story
    <class 'bs4.element.NavigableString'>
    The Dormouse`s story
    <class 'str'>
    The Dormouse`s story
    <class 'str'>
    The Dormouse`s story
    <class 'str'>
    
    四種方法都可以獲取到節點內容,但是隻有string型別是BeautifulSoup自定義的型別
    其他都是str型別
    

3.巢狀選擇

print(soup.head.title)
print(type(soup.head.title))

<title>The Dormouse`s story</title>
<class 'bs4.element.Tag'>

往後面“.”就完了。

4.關聯選擇

  • 子節點和子孫節點

    我們之前使用
    print(soup.title)
    打印出了包括節點在內的所有內容
    
<p class="story">
        Once upon a time there were three little sisters; and their names were
        <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
    and
    <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
</p>
    使用soup.p打印出了包括節點的所有內容並且有格式
    此結果型別為BeautifulSoup的tag型別

    下面我們使用
    print(soup.p.contents)
['\n        Once upon a time there were three little sisters; and their names were\n        ', <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>, '\n', <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, '\n    and\n    ', <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>, '\n']

<class 'list'>
打印出來了什麼?
節點內部所有的東西
既然是個list型別,我們看看list裡所有型別
0   <class 'bs4.element.NavigableString'>   
        Once upon a time there were three little sisters; and their names were

1   <class 'bs4.element.Tag'>   <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>
2   <class 'bs4.element.NavigableString'>   

3   <class 'bs4.element.Tag'>   <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
4   <class 'bs4.element.NavigableString'>   
    and

5   <class 'bs4.element.Tag'>   <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
6   <class 'bs4.element.NavigableString'> 
主要有BeautifulSoup自定義的string型別和節點tag型別

然後我們看子節點和子孫節點
子節點:
print(soup.p.children)
print(type(soup.p.children))
for i,child in soup.p.children:
    print(i," ",type(child)," ",child)
<list_iterator object at 0x0000000012F87A58>
<class 'list_iterator'> # 列表迭代物件
0   <class 'bs4.element.NavigableString'>   
        Once upon a time there were three little sisters; and their names were

1   <class 'bs4.element.Tag'>   <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>
2   <class 'bs4.element.NavigableString'>   

3   <class 'bs4.element.Tag'>   <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
4   <class 'bs4.element.NavigableString'>   
    and

5   <class 'bs4.element.Tag'>   <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
6   <class 'bs4.element.NavigableString'> 

和我們上面的是一樣的結果。

子孫節點:
子孫節點使用的descendants
print(soup.p.descendants)
print(type(soup.p.descendants))
for i,d in enumerate(soup.p.descendants):
    print(i,' ',type(d),' ', d)
<generator object Tag.descendants at 0x0000000012F81570>
<class 'generator'> # 生成器物件
0   <class 'bs4.element.NavigableString'>   
        Once upon a time there were three little sisters; and their names were

1   <class 'bs4.element.Tag'>   <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>
2   <class 'bs4.element.NavigableString'>   

3   <class 'bs4.element.Tag'>   <span>Elsie</span>
4   <class 'bs4.element.NavigableString'>   Elsie
5   <class 'bs4.element.NavigableString'>   

6   <class 'bs4.element.NavigableString'>   

7   <class 'bs4.element.Tag'>   <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
8   <class 'bs4.element.NavigableString'>   Lacie
9   <class 'bs4.element.NavigableString'>   
    and

10   <class 'bs4.element.Tag'>   <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
11   <class 'bs4.element.NavigableString'>   Tillie
12   <class 'bs4.element.NavigableString'>

從結果我們可以看出,在使用子孫節點descendants的時候,就相當於,使用children方法,遇到了節點tag物件,則對子節點使用children方法,以此類推,直到所有子孫全部列出來

  • 父節點和祖先節點

    父節點:
    使用parent
    print(type(soup.p.parent))
    print(soup.p.parent)
    
<class 'bs4.element.Tag'>
<body><p class="story">
        Once upon a time there were three little sisters; and their names were
        <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
    and
    <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
</p>
<p class="story">...</p>
</body>
p節點的父親節點是body節點,返回的是body節點

祖先節點:

使用的是parents
print(type(soup.p.parents))
print(soup.p.parents)

for i, p in enumerate(soup.p.parents):
    print(i, ' ', type(p), ' ', p)
<class 'generator'>
<generator object PageElement.parents at 0x0000000012F50570>
0   <class 'bs4.element.Tag'>   <body><p class="story">
        Once upon a time there were three little sisters; and their names were
        <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
    and
    <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
</p>
<p class="story">...</p>
</body>
1   <class 'bs4.element.Tag'>   <html>
<head>
<title>The Dormouse`s story</title>
</head><body><p class="story">
        Once upon a time there were three little sisters; and their names were
        <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
    and
    <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
</p>
<p class="story">...</p>
</body></html>
2   <class 'bs4.BeautifulSoup'>   <html>
<head>
<title>The Dormouse`s story</title>
</head><body><p class="story">
        Once upon a time there were three little sisters; and their names were
        <a class="sister" href="http://exmple.com/elsie" id="link1">
<span>Elsie</span>
</a>
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
    and
    <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
</p>
<p class="story">...</p>
</body></html>

返回一個生成器物件
一個一個節點往外走,直到走到最後一個總節點
第一個其實就是父節點
next(soup.p.parents)就是父節點

  • 兄弟節點

    兄弟節點(同級節點)使用的是sibling和siblings
    這裡的兄弟分這此節點的前兄弟和後兄弟,即 previous_sibling,和next_sibling
    也可以找到前面的兄弟們和後面的兄弟們,即 previous_siblings,和next_siblings
    以後面的兄弟們為例:
    print(soup.span.next_siblings)
    
    for i, s in enumerate(soup.a.next_siblings):
        print(i, " ", type(s), " ", s)
    
<generator object PageElement.next_siblings at 0x0000000012F90570>
0   <class 'bs4.element.NavigableString'>   

1   <class 'bs4.element.Tag'>   <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
2   <class 'bs4.element.NavigableString'>   
    and

3   <class 'bs4.element.Tag'>   <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
4   <class 'bs4.element.NavigableString'> 
這裡我們看到無論是BeautifulSoup的自定義string型別還是自定義tag節點型別
只要是同級都是兄弟
  • 獲取屬性值

    當我們要獲取節點屬性的時候,需要這樣做
    獲取節點所有的屬性:soup.p.attrs
    獲取節點某個屬性:soup.p.attrs[‘xxx’]
    或soup.p[‘xxx’]

    print(soup.p.attrs)
    print(type(soup.p.attrs))
    print(soup.p.attrs[‘class’])
    print(soup.p[‘class’])

{'class': ['story']}
<class 'dict'>
['story']
['story']

四、方法選擇器

1.find_all()

  • name
# 導包
from bs4 import BeautifulSoup
# data source
html = '''
    <div class="palnel">
    <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>
'''
# import data
soup = BeautifulSoup(html,'lxml')
# research data
print(soup.find_all(name='ul'))

返回值:
列表內有兩個ul節點
[<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>]

節點可以繼續find_all()

for ul in soup.find_all(name='ul'):
    for li in ul.find_all(name='li'):
        print(li.string)
  • attrs

    按照屬性查詢
    attrs={'class'='list'}
    # 查詢class屬性包括list的節點值
    print(soup.find_all(attrs={'class':'list'}))
    
返回值是個列表 , 記住是包括,不是等於
attrs={} 這裡面是個字典 可以多個屬性和屬性值對應起來查詢
[<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>]
  • text

    匹配文字
    # 查詢text包括link的文字
    print(soup.find_all(text=re.compile('Foo',re.I)))
    ['Foo', 'Foo', 'Foo']
    注意這樣搜尋出來的是文字列表,並不是節點列表
    
    當然name,attrs,text三個可以結合起來用進行節點查詢
    
    print(soup.find_all(
            name='li', 
            attrs={'class': 'element'}, 
            text=re.compile('Foo')))
    
    查詢節點名稱為li,class屬性為element,文字為Foo的節點
    
返回值為節點列表
[<li class="element">Foo</li>, 
<li class="element">Foo</li>, <li class="element">Foo</li>]

2.find()

和之前的find_all()使用方法一樣,
只不過帶all的是返回的列表,不帶all的返回的是列表中的第一個

3.find_parents()和find_parent()

返回祖先節點和父節點

4.find_next_siblings()和find_next_sibling()

返回後面所有的兄弟節點和返回後面第一個兄弟節點

5.find_previous_siblings()和find_previous_sibling()

返回前面所有的兄弟節點和返回前面第一個兄弟節點

6.find_previous_siblings()和find_previous_sibling()

返回前面所有的兄弟節點和返回前面第一個兄弟節點

7.find_all_next()和find_next()

返回之後所有符合條件的節點和返回之後符合條件的第一個節點

8.find_all_previous()和find_previous()

返回前面所有符合條件的節點和返回前面符合條件的第一個節點

注意:不管是find,find_all,find_previous_siblings等等
上述所有關於方法選擇器的都可以使用name 、attrs 、text進行限定
方法名是為了選擇查詢的範圍,屬性是進行精確的限制,兩者組合找到最後結果

五、CSS選擇器

利用select選擇
# 選擇class屬性值為panel下的class屬性為panel-heading的節點
soup.select('.panel .panel-heading')
# 選擇id為list-2的節點下的class屬性為element的節點列表
soup.select('#list-2 .element')
# 選擇所有lu節點
soup.select('lu')

1.巢狀選擇

for ul in soup.select('ul'):
    print(ul.select('li'))
[<li class="element">Foo</li>, <li class="element">Bar</li>,
 <li class="element">Jay</li>]
[<li class="element">Foo</li>, <li class="element">Bar</li>]

2.屬性獲取

for ul in soup.select('ul'):
    # 這下面等於是再用節點選擇器中的方法
    print(ul.attrs)
    print(ul.attrs['id'])
    print(ul['id'])
{'class': ['list'], 'id': 'list-1'}
list-1
list-1
{'class': ['list', 'list-small'], 'id': 'list-2'}
list-2
list-2
{'class': ['list', 'list-small'], 'id': 'list-2'}
list-2
list-2

3.獲取文字

這下面等於是再用節點選擇器中的方法
print(soup.p.text)
print(soup.p.string)

總結:
使用(html,’lxml’)
節點選擇功能弱,但是快啊
使用find/find_all()篩選多個或者單個結果
若熟悉CSS 可以使用select

相關推薦

Python學習筆記——pycharm 爬蟲Beautiful soup

昨天看了看Beautiful soup,看的我真的是一臉懵逼,lxml的全忘光了,兩個光混淆。很難受 一、安裝 安裝Beautiful soup 和 lxml庫 二、基本用法 # 資料來源 html = ''' <html>

爬蟲學習筆記(五) Beautiful Soup使用

內容 BE 是否 ini n-n 修改 過濾 性能測試 刪除 上篇博客說了正則表達式,但是正則學起來比較費勁,寫的時候也不好寫,這次說下Beautiful Soup怎麽用,這個模塊是用來解析html的,它操作很簡單,用起來比較方便,比正則學習起來簡單多了。 這是第三方模塊需

python學習筆記】37認識Scrapy爬蟲,爬取滬深A股資訊

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 認識Scrapy爬蟲 安裝 書上說在pip安裝會有問題,直接在Anaconda裡安裝。 建立Scrapy專案 PyCharm裡沒有直接的建立入口,在命令列建立(從Anaconda安裝後似乎自動就

python學習筆記】35爬蟲基礎和相關產品API(和風天氣)使用例項

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 在網站URL後面跟robots.txt一般就可以看到網站允許和禁止爬取的資源。 GET請求獲取響應內容 最基本的爬蟲。 import requests ''' 中國旅遊網 /www.cntour.

Python學習筆記——pycharm web伺服器搭建(5)概括開發流程

開發流程: 利用pycharm建立專案 建立應用 (python manage.py startapp 應用名稱)建立後在專案settings中註冊 模型類的定義 (在應用的models.py中定義

Python學習筆記——pycharm web伺服器搭建(6)Django模型知識點

這篇文章用於記錄Django模型相關知識,發現有需要補充的會隨時新增 僅用於記錄,以後方便自己查閱,至於大家能不能看懂,我覺得隨緣就行。 1、自定義模型管理器 一般情況下,我們定義的模型類如下 class BookInfo(models.Mo

Python學習筆記——pycharm web伺服器搭建(9)其他知識點

一、靜態檔案 我們要在網頁中載入一張圖,如何做? settings中新增程式碼: STATIC_URL = '/static/'(已經存在) STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static

Python 學習筆記10 - 實戰微信遙控電腦

10、Python實戰:微信遙控電腦 1 微信遠控:Python控制電腦的兩種方法 1-1 課程介紹   微信控制電腦   網頁控制電腦   遠端控制軟體   1-2 命令提示符 CMD 入門 基本的CMD命令介紹

python學習筆記】36抓取去哪兒網的旅遊產品資料

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 書上這章開篇就說了儘量找JSON格式的資料,比較方便解析(在python裡直接轉換成字典),去哪兒網PC端返回的不是JSON資料,這裡抓取的是它的移動端的資料。 如果是就散落在網頁上,我覺得就像上篇學習的那

python學習筆記】41認識Pandas中的資料變形

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 Pandas資料變形 關於stack()和unstack()見這裡和這裡。 import pandas as pd import numpy as np # 讀取杭州天氣檔案 df = pd.read

python學習筆記】40Pandas中DataFrame的分組/分割/合併

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 DataFrame分組操作 注意分組後得到的就是Series物件了,而不再是DataFrame物件。 import pandas as pd # 還是讀取這份檔案 df = pd.read_csv("

python學習筆記】39認識SQLAlchemy,簡單操作Pandas中的DataFrame

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 認識SQLAlchemy SQLAlchemy是Python的ORM工具,就像Java有Hibernate一樣,實現關係型資料庫中的記錄與Python自定義Class的物件的轉化,實現操作之間的對映。

python學習筆記】38使用Selenium抓取去哪兒網動態頁面

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 在去哪兒網PC端自由行頁面,使用者需要輸入出發地和目的地,點選開始定製,然後就可以看到一系列相關的旅遊產品。在這個旅遊產品頁換頁不會改變URL,而是重新載入,這時頁碼沒有體現在URL中,這種動態頁面用傳統的爬蟲

python學習筆記】45認識Matplotlib和pyecharts資料視覺化

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 Matplotlib資料視覺化 資料準備 import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv("E:/Data/p

python學習筆記】44Series.apply()列資料批量處理,Series.str.extract()正則匹配

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 Series.apply()列資料批量處理 先將該列取出,形成Series物件,再呼叫apply()方法傳入用於處理的函式,這個過程就像map()一樣。 import pandas as pd # 各

python學習筆記】43Pandas時序資料處理

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 Python中時間的一些常用操作 import time # 從格林威治時間到現在,單位秒 print('系統時間戳:', time.time()) print('本地時間按格式轉成str:', tim

python學習筆記】42Pandas資料缺失值/異常值/重複值處理

學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 缺失值處理 Pandas資料物件中的缺失值表示為NaN。 import pandas as pd # 讀取杭州天氣檔案 df = pd.read_csv("E:/Data/practice/hz_we

python學習筆記】46隨機漫步,埃拉托色尼篩法,蒙特卡洛演算法,多項式迴歸

學習《Python與機器學習實戰》和《scikit-learn機器學習》時的一些實踐。 隨機漫步 import matplotlib.pyplot as plt import numpy as np ''' 一維隨機漫步 ''' # 博弈組數 n_person = 20

python學習筆記-Pycharm遠程連接服務器的Python虛擬環境(Virtualenv)

charm 由於 next fin 啟動 學習 class 正常 虛擬環境 Virtualenv可以作為一個獨立的Python虛擬環境工具,並能夠建立多個相互獨立,互不影響的Python工作環境。 主要解決在運行多個項目時,由於它們對應的運行環境需求不同,可能會導致項目無法

python學習筆記】33生成器、迭代器、高階函式

生成器 生成器(generator)相比列表推導式,只佔用很小的空間,因為它是一邊迴圈一邊推算,通過next()呼叫下一元素,並在結束時丟擲StopIteration異常,在語法上只要把[]換成()即可