常用的類庫為lxml, BeautifulSoup, re(正則)
以獲取豆瓣電影正在熱映的電影名為例,url='https://movie.douban.com/cinema/nowplaying/beijing/'
網頁分析
部分網頁源碼
<ul class="lists">
<li
id="3878007"
class="list-item"
data-title="海王"
data-score="8.2"
data-star="40"
data-release="2018"
data-duration="143分鍾"
data-region="美國 澳大利亞"
data-director="溫子仁"
data-actors="傑森·莫瑪 / 艾梅柏·希爾德 / 威廉·達福"
data-category="nowplaying"
data-enough="True"
data-showed="True"
data-votecount="105013"
data-subject="3878007"
>
分析可知我們要的電影名稱信息在li標簽的data-title屬性里
下面開始寫代碼
爬蟲源碼展示
import requests
from lxml import etree # 導入庫
from bs4 import BeautifulSoup
import re
import time
# 定義爬蟲類
class Spider():
def __init__(self):
self.url = 'https://movie.douban.com/cinema/nowplaying/beijing/'
self.headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
}
r = requests.get(self.url,headers=self.headers)
r.encoding = r.apparent_encoding
self.html = r.text
def lxml_find(self):
'''用lxml解析'''
start = time.time() # 三種方式速度對比
selector = etree.HTML(self.html) # 轉換為lxml解析的對象
titles = selector.xpath('//li[@class="list-item"]/@data-title') # 這里返回的是一個列表
for each in titles:
title = each.strip() # 去掉字符左右的空格
print(title)
end = time.time()
print('lxml耗時', end-start)
def BeautifulSoup_find(self):
'''用BeautifulSoup解析'''
start = time.time()
soup = BeautifulSoup(self.html, 'lxml') # 轉換為BeautifulSoup的解析對象()里第二個參數為解析方式
titles = soup.find_all('li', class_='list-item')
for each in titles:
title = each['data-title']
print(title)
end = time.time()
print('BeautifulSoup耗時', end-start)
def re_find(self):
'''用re解析'''
start = time.time()
titles = re.findall('data-title="(.+)"',self.html)
for each in titles:
print(each)
end = time.time()
print('re耗時', end-start)
if __name__ == '__main__':
spider = Spider()
spider.lxml_find()
spider.BeautifulSoup_find()
spider.re_find()
輸出結果
海王
無名之輩
無敵破壞王2:大鬧互聯網
狗十三
驚濤颶浪
毒液:致命守護者
憨豆特工3
神奇動物:格林德沃之罪
恐龍王
老爸102歲
生活萬歲
進擊的男孩
摘金奇緣
亡命救贖
一百年很長嗎
雲上日出
誰是壞孩子
照相師
緣·夢
網絡謎蹤
龍貓
印度合伙人
綠毛怪格林奇
最萌警探
春天的馬拉松
lxml耗時 0.007623910903930664
海王
無名之輩
無敵破壞王2:大鬧互聯網
狗十三
驚濤颶浪
毒液:致命守護者
憨豆特工3
神奇動物:格林德沃之罪
恐龍王
老爸102歲
生活萬歲
進擊的男孩
摘金奇緣
亡命救贖
一百年很長嗎
超時空大冒險
天渠
愛不可及
二十歲
你好,之華
冒牌搭檔
鐵甲戰神
克隆人
恐怖快遞
中國藍盔
阿凡提之奇緣歷險
名偵探柯南:零的執行人
為邁克爾·傑克遜鑄造雕像
再見仍是朋友
心迷宮
淡藍琥珀
阿拉姜色
兩個俏公主
雲上日出
誰是壞孩子
照相師
緣·夢
網絡謎蹤
龍貓
印度合伙人
綠毛怪格林奇
最萌警探
春天的馬拉松
BeautifulSoup耗時 0.061043500900268555
海王
無名之輩
無敵破壞王2:大鬧互聯網
狗十三
驚濤颶浪
毒液:致命守護者
憨豆特工3
神奇動物:格林德沃之罪
恐龍王
老爸102歲
生活萬歲
進擊的男孩
摘金奇緣
亡命救贖
一百年很長嗎
超時空大冒險
天渠
愛不可及
二十歲
你好,之華
冒牌搭檔
鐵甲戰神
克隆人
恐怖快遞
中國藍盔
阿凡提之奇緣歷險
名偵探柯南:零的執行人
為邁克爾·傑克遜鑄造雕像
再見仍是朋友
心迷宮
淡藍琥珀
阿拉姜色
兩個俏公主
雲上日出
誰是壞孩子
照相師
緣·夢
網絡謎蹤
龍貓
印度合伙人
綠毛怪格林奇
最萌警探
春天的馬拉松
re耗時 0.0004856586456298828
代碼說明
1. lxml
lxml是通過xpath來查找
使用前需使用調用ertee.HTML()方法('()'內填HTML代碼)生成一個可查找的對象
常用xpath語法如下
// 兩個斜杠為向下查找孫子標簽
/ 一個斜杠為查找直接兒子標簽
[] 方括號內填標簽屬性,如查找class屬性為name的a標簽,格式為a[@class="name"]
/text() 取出標簽的內容,如查找網頁中的 <a class="name">KAINHUCK</a> 中的KAINHUCK,格式為//a[@class="name"]/text()
/@attr 取出標簽的屬性,如查找網頁中的 <a class="name">KAINHUCK</a> 中的class屬性值name,格式為//a[@class="name"]/@class
2. BeautifulSoup
使用前需先將HTML轉換為課查找對象,格式為
BeautifulSoup(html, 'lxml')
html 為HTML代碼, 后面的參數為轉換方法(其他方法有'html.parser' , 'html5lib', 推薦使用'lxml')
查找方法
info = find('a', id='kain') 查找第一個id屬性為kain的a標簽,並存進info變量中(其他標簽同理)
find_all('a', class_='name') 查找所有class屬性為name的a標簽(注:class屬性需寫成'class_')
info.p.text 獲取第一個id屬性為kain的a標簽下的p標簽的內容(info為上面例子里的info,其他同理)
info.p['name'] 獲取第一個id屬性為kain的a標簽下的p標簽的name屬性值(info為上面例子里的info,其他同理)
當代碼中有很多同級標簽時
<p class='info-list'> <a class='name'>text1</a> <a class='name'>text2</a> <a class='name'>text3</a> <a class='name'>text4</a> </p>
示例代碼如下
from bs4 import BeautifulSoup html = ''' <p class='info-list'> <a class='name'>text1</a> <a class='name'>text2</a> <a class='name'>text3</a> <a class='name'>text4</a> </p> ''' soup = BeautifulSoup(html, 'lxml') texts = soup.find('p', class_='info-list') print(texts.contents[1].text) # 輸出text1 print(texts.contents[2].text) # 輸出text2 print(texts.contents[3].text) # 輸出text3 print(texts.contents[4].text) # 輸出text4
注意:不是從0開始
3. re(正則表達式)
正則表達式內容較多,大家可以參考這里
總結
使用lxml查找時可以在目標網頁按F12調出開發者窗口然后再在按Ctrl+f查找,在查找欄里輸入你的xpath語法可以檢查是否能找到對應內容
可以從看例子的輸出中看出三種方法的速度
lxml耗時 0.007623910903930664
BeautifulSoup耗時 0.061043500900268555
re耗時 0.0004856586456298828
對以上三種最常用的解析網頁的方法做個對比
lxml | BeautifulSoup | re | |
---|---|---|---|
語法難易度 | 簡單 | 簡單 | 復雜 |
查找速度 | 較快 | 慢 | 快 |
綜上,對於網頁內容的解析,這里推薦新手使用lxml方法,而對速度有要求就使用正則表達式(入門有點困難)