1. 程式人生 > >Python爬蟲解析網頁的三種方法,lxml、BeautifulSoup、re案例!

Python爬蟲解析網頁的三種方法,lxml、BeautifulSoup、re案例!

常用的類庫為lxml,BeautifulSoup,re(正則)

 學習Python中有不明白推薦加入交流群
                號:960410445
                群裡有志同道合的小夥伴,互幫互助,
                群裡有不錯的視訊學習教程和PDF!

	以獲取豆瓣電影正在熱映的電影名為例,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
神奇動物:格林德沃之罪.......................

程式碼說明

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

對以上三種最常用的解析網頁的方法做個對比

Python爬蟲解析網頁的三種方法,lxml、BeautifulSoup、re案例!

 

綜上,對於網頁內容的解析,這裡推薦新手使用lxml方法,而對速度有要求就使用正則表示式(入門有點困難)