python爬蟲從入門到放棄(六)之 BeautifulSoup庫的使用

上一篇文章的正則,其實對很多人來說用起來是不方便的,加上需要記很多規則,所以用起來不是特別熟練,而這節我們提到的beautifulsoup就是一個非常強大的工具,爬蟲利器。

beautifulSoup “美味的湯,綠色的濃湯”

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

快速使用

通過下面的一個例子,對bs4有個簡單的了解,以及看一下它的強大之處:

from bs4 import BeautifulSouphtml = '''
<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'))

結果如下:

使用BeautifulSoup解析這段代碼,能夠得到一個 BeautifulSoup 的對象,并能按照標準的縮進格式的結構輸出。

同時我們通過下面代碼可以分別獲取所有的鏈接,以及文字內容:

for link in soup.find_all('a'):print(link.get('href'))print(soup.get_text())

解析器

Beautiful Soup支持Python標準庫中的HTML解析器,還支持一些第三方的解析器,如果我們不安裝它,則 Python 會使用 Python默認的解析器,lxml 解析器更加強大,速度更快,推薦安裝。

下面是常見解析器:

推薦使用lxml作為解析器,因為效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必須安裝lxml或html5lib, 因為那些Python版本的標準庫中內置的HTML解析方法不夠穩定.

基本使用

標簽選擇器

在快速使用中我們添加如下代碼:
print(soup.title)
print(type(soup.title))
print(soup.head)
print(soup.p)

通過這種soup.標簽名 我們就可以獲得這個標簽的內容
這里有個問題需要注意,通過這種方式獲取標簽,如果文檔中有多個這樣的標簽,返回的結果是第一個標簽的內容,如上面我們通過soup.p獲取p標簽,而文檔中有多個p標簽,但是只返回了第一個p標簽內容

獲取名稱

當我們通過soup.title.name的時候就可以獲得該title標簽的名稱,即title

獲取屬性

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

獲取內容

print(soup.p.string)
結果就可以獲取第一個p標簽的內容:
The Dormouse's story

嵌套選擇

我們直接可以通過下面嵌套的方式獲取

print(soup.head.title.string)

子節點和子孫節點

contents的使用
通過下面例子演示:

html = """
<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 href="http://example.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>and they lived at the bottom of a well.</p><p class="story">...</p>
"""from bs4 import BeautifulSoupsoup = BeautifulSoup(html,'lxml')
print(soup.p.contents)

結果是將p標簽下的所有子標簽存入到了一個列表中

列表中會存入如下元素

children的使用

通過下面的方式也可以獲取p標簽下的所有子節點內容和通過contents獲取的結果是一樣的,但是不同的地方是soup.p.children是一個迭代對象,而不是列表,只能通過循環的方式獲取素有的信息

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

通過contents以及children都是獲取子節點,如果想要獲取子孫節點可以通過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_all

find_all(name,attrs,recursive,text,**kwargs)
可以根據標簽名,屬性,內容查找文檔

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'))

attrs

例子如下:

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'}))

attrs可以傳入字典的方式來查找標簽,但是這里有個特殊的就是class,因為class在python中是特殊的字段,所以如果想要查找class相關的可以更改attrs={'class_':'element'}或者soup.find_all('',{"class":"element}),特殊的標簽屬性可以不寫attrs,例如id

text

例子如下:

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'))

結果返回的是查到的所有的text='Foo'的文本

find

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

其他一些類似的用法:
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()返回第一個符合條件的節點

CSS選擇器

通過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]))

獲取內容

通過get_text()就可以獲取文本內容

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')
for li in soup.select('li'):print(li.get_text())

獲取屬性
或者屬性的時候可以通過[屬性名]或者attrs[屬性名]

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')
for ul in soup.select('ul'):print(ul['id'])print(ul.attrs['id'])

總結

推薦使用lxml解析庫,必要時使用html.parser
標簽選擇篩選功能弱但是速度快
建議使用find()、find_all() 查詢匹配單個結果或者多個結果
如果對CSS選擇器熟悉建議使用select()
記住常用的獲取屬性和文本值的方法

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/456345.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/456345.shtml
英文地址,請注明出處:http://en.pswp.cn/news/456345.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SparkHiveSQL中Join操作的謂詞下推?

前言&#xff1a; SparkSQL和HiveSQL的Join操作中也有謂詞下推&#xff1f;今天就通過大神的文章來了解下。同樣&#xff0c;如有冒犯&#xff0c;請聯系。 正文 上文簡要介紹了Join在大數據領域中的使用背景以及常用的幾種算法&#xff0d;broadcast hash join 、shuffle h…

【轉載】通過金礦模型介紹動態規劃 (動態規劃入門)

先附上原文地址&#xff1a;http://www.cnblogs.com/sdjl/articles/1274312.html 通過金礦模型介紹動態規劃 對于動態規劃&#xff0c;每個剛接觸的人都需要一段時間來理解&#xff0c;特別是第一次接觸的時候總是想不通為什么這種方法可行&#xff0c;這篇文章就是為了…

flask模型中【外鍵】relationship的使用筆記

模型中relationship的使用筆記 模型.PY class User(db.Model):# __tablename__ user1 #定義表名id db.Column(db.Integer, primary_keyTrue, autoincrementTrue)username db.Column(db.String(10), nullableTrue)password db.Column(db.String(64), nullableTrue)phone …

六種方式實現生產者消費者(未完)

2019獨角獸企業重金招聘Python工程師標準>>> 一、利用Object對象是wait和notify\notifyAll package com.jv.parallel.consumerandproducer.objectwait;public class Car {private volatile int flag 0;public void showConsumer(){System.out.println("I am a…

SQL中基于代價的優化

還記得筆者在上篇文章無意中挖的一個坑么&#xff1f;如若不知&#xff0c;強烈建議看官先行閱讀前面兩文&#xff0d;《SparkSQL Join原理》和《Join中竟然也有謂詞下推?》 第一篇文章主要分析了大數據領域Join的三種基礎算法以及各自的適用場景&#xff0c;第二篇文章在第一…

git如何解決沖突(代碼托管在coding)

分支A提交合并請求到分支B&#xff0c;有沖突git fetch code 拉取遠程倉庫的其他分支代碼&#xff08;我拉代碼是remote add code所以這里是code,可以用git remote查看&#xff09;git checkout 分支A 切換到分支Agit pull code 分支A 拉取分支A代碼git checkout 分支B 切換到分…

cookie和session之會話機制: ? http 協議? ---》 無狀態協議

設置cookie&#xff1a; 通過response對象&#xff1a; response make_response() response.set_cookie(key,value,max_age(單位second),expires(要求是detetime類型)) expires datetime(year2018,month11,day5) #expires是這么設置的 expires datetime.n…

Java Map 怎樣實現Key 的唯一性?

大家都知道。在Map和Set不可存在反復元素&#xff1f; 可是對于內部的細節我們并不了解。今天我們就一塊來 探討一下&#xff01; 1 對于 HashMap HashSet 他們的底層數據結構的實現是&#xff1a;維護了一張 HashTable 。容器中的元素所有存儲在Hashtable 中。他們再加入…

win10下安裝pyspark及碰到的問題

文章目錄前言安裝過程Q1總結&#xff1a;前言 最近由于工作需要&#xff0c;需要了解下pyspark&#xff0c;所以就在win10環境下裝了下&#xff0c;然后在pycharm中使用的時候碰到了一些問題。整個過程可謂是一波三折。下面一一道來。 安裝過程 安裝過程就不詳細說了&#x…

解決AttributeError AttributeError: 'NoneType' object has no attribute 'filename'

原因忘記上傳文件 表單需要加屬性 enctype"multipart/form-data" 否則報錯&#xff01;AttributeError AttributeError: NoneType object has no attribute filename enctype"multipart/form-data是設置表單的MIME編碼。默認情況&#xff0c;這個編碼格式是ap…

SQLAlchemy()分頁器paginate方法

Flask的數據分頁示例 用法&#xff1a; 1&#xff0c;首先寫數據獲取的視圖函數&#xff0c;就像這樣&#xff1a; # 首頁 blog_bp.route(/, endpointindex) def index():#獲取頁數page request.args.get(page,1)paginate Article.query.paginate(pageint(page),per_page3)…

開源中國 2014 年源創會年度計劃

時光總是從敲代碼的指尖不經意地滑過&#xff0c;轉眼2014年已快過去一半&#xff0c;OSC依然心懷著最初的夢想。 源創會&#xff0c;oscer的線下快樂大本營&#xff0c;我們仍在繼續...... 聆聽技術大牛講解最前沿的技術&#xff0c;和同道中人切磋IT秘籍&#xff0c;吃點心侃…

互聯網金融行業申請評分卡(A卡)簡介

文章目錄前言基本概念1、信用違約風險的基本概念什么是信用違約風險&#xff1a;組成部分違約的主體個貸中常用的違約定義M0&#xff0c;M1&#xff0c;M2的定義2、申請評分卡的重要性和特性信貸場景中的評分卡申請評分卡的概念為什么要開發申請評分卡評分卡的特性 &#xff08…

Flask的csrf_token的用法

在flask當中&#xff0c;flask-wtf模塊時攜帶csrf校驗的&#xff0c;只是需要開啟&#xff1b; 如果不開啟校驗就不需要校驗&#xff0c;但是那樣不安全。 Csrf是針對與post請求的跨域限制&#xff0c;get請求沒有作用 csrf_token的開啟 在flask中開啟csrf保護 from flask_…

dotty編譯器語法特性之一交叉類型,聯合類型和文本單例類型

2019獨角獸企業重金招聘Python工程師標準>>> ###翻譯&#xff1a;http://dotty.epfl.ch/docs/reference/intersection-types.html #交叉類型 trait Resettable {def reset(): this.type } trait Growable[T] {def add(x: T): this.type } def f(x: Resettable &…

【轉】Zookeeper 安裝和配置

轉自&#xff1a;http://coolxing.iteye.com/blog/1871009 Zookeeper的安裝和配置十分簡單, 既可以配置成單機模式, 也可以配置成集群模式. 下面將分別進行介紹. 單機模式 1. 配置 點擊這里下載zookeeper的安裝包之后, 解壓到合適目錄. 進入zookeeper目錄下的conf子目錄, 創建z…

一分鐘精通Flask-Bootstrap的使用

要想在程序中集成Bootstrap&#xff0c;顯然要對模板做所有必要的改動。不過&#xff0c;更簡單的方法是使用一個名為Flask-Bootstrap 的Flask 擴展&#xff0c;簡化集成的過程。 安裝&#xff1a; Flask-Bootstrap 使用pip安裝&#xff1a; pip install flask_bootstrap Fl…

linux生產環境下安裝anaconda總結

前言&#xff1a; 工作中&#xff0c;常常要在新的linux生產服務器中安裝自己的集成python環境&#xff0c;這種情況下有一點需要注意&#xff1a;不能覆蓋生產服務器中的python環境&#xff08;也就是自己的python環境要和系統的python環境分開&#xff09;。一般情況下系統自…

Delphi TScrollBar 用于滾動窗口、組件內容

滾動條組件&#xff08;TScrollBar&#xff09;此組件是一個Windows滾動條&#xff0c;用于滾動窗口、組件內容。許多控制有滾動條屬性&#xff0c;它們把滾動條作為自己的一部分&#xff0c;對于沒有完整滾動條的控制&#xff0c;TScrollBar組件提供了一個附加的功能&#xff…

FSF 稱 DRM 被用于鎖定、控制和監視用戶

自由軟件基金會正在督促美國政府廢除DMCA中保護DRM的反規避條款。DMCA的1201條款禁止繞過DRM保護的內容和設備。 自由軟件基金會的Donald Robertson在致函美國版權辦公室的信&#xff08;PDF&#xff09;中指出&#xff0c;技術保護措施和數字限制管理&#xff08;即DRM&#x…