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學習筆記】40:Pandas中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學習筆記】44:Series.apply()列資料批量處理,Series.str.extract()正則匹配
學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 Series.apply()列資料批量處理 先將該列取出,形成Series物件,再呼叫apply()方法傳入用於處理的函式,這個過程就像map()一樣。 import pandas as pd # 各
【python學習筆記】43:Pandas時序資料處理
學習《Python3爬蟲、資料清洗與視覺化實戰》時自己的一些實踐。 Python中時間的一些常用操作 import time # 從格林威治時間到現在,單位秒 print('系統時間戳:', time.time()) print('本地時間按格式轉成str:', tim
【python學習筆記】42:Pandas資料缺失值/異常值/重複值處理
學習《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異常,在語法上只要把[]換成()即可