知己知彼,案例對(duì)比 Requests、Selenium、Scrapy 爬蟲(chóng)庫(kù)!
經(jīng)常有讀者會(huì)爬蟲(chóng)學(xué)哪個(gè)庫(kù)?其實(shí)常用的 Python 爬蟲(chóng)庫(kù)無(wú)非是requests,selenium和scrapy,且每個(gè)庫(kù)都有他們的特點(diǎn),對(duì)于我來(lái)說(shuō)沒(méi)有最推薦的庫(kù)只有最合適庫(kù),本文就將基于一個(gè)簡(jiǎn)單的爬蟲(chóng)案例(Python爬取起點(diǎn)中文網(wǎng))來(lái)對(duì)比分析(從時(shí)間角度)三個(gè)庫(kù)

目標(biāo)需求為批量采集排行榜書(shū)籍信息,如下圖所示:
頁(yè)面結(jié)構(gòu)很容易分析出來(lái),排行榜100條書(shū)籍信息,一個(gè)靜態(tài)頁(yè)面包含20條數(shù)據(jù)。使用不同的第三方庫(kù)進(jìn)行數(shù)據(jù)解析并提取數(shù)據(jù),分別是:
requests selenium Scrapy
然后再邏輯代碼的開(kāi)頭和結(jié)尾加上時(shí)間戳,得到程序運(yùn)行時(shí)間,進(jìn)行效率對(duì)比。
這里由于都是使用xpath提取數(shù)據(jù),三種方式xpath語(yǔ)句大同小異,這里提前數(shù)據(jù)解析說(shuō)明:

1. imgLink: //div[@class='book-img-text']/ul/li/div[1]/a/@href
2. title: //div[@class='book-img-text']/ul/li//div[2]/h4/a/text()
3. author: //div[@class='book-img-text']/ul/li/div[2]/p[1]/a[1]/text()
4. intro: //div[@class='book-img-text']/ul/li/div[2]/p[2]/text()
5. update://div[@class='book-img-text']/ul/li/div[2]/p[3]/a/text()
一、requests
首先導(dǎo)入相關(guān)庫(kù)
from lxml import etree
import requests
import time
邏輯代碼如下
start = time.time() # 開(kāi)始計(jì)時(shí)?
url = 'https://www.qidian.com/rank/yuepiao?style=1&page=1'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36'
}
page = requests.get(url,headers=headers)
html = etree.HTML(page.content.decode('utf-8'))
books = html.xpath("http://div[@class='book-img-text']/ul/li")
for book in books:
imglink = 'https:' + book.xpath("./div[1]/a/@href")[0]
# 其它信息xpath提取,這里省略 ....
update = book.xpath("./div[2]/p[3]/a/text()")[0]
print(imglink,title,author,intro,update)
end = time.time() # 結(jié)束計(jì)時(shí)?
print(end-start)
程序運(yùn)行結(jié)果如下
可以看到用時(shí) 0.823s 將全部數(shù)據(jù)爬取下來(lái)。
二、 selenium
首先導(dǎo)入相關(guān)庫(kù)
import time
from selenium import webdriver
代碼實(shí)現(xiàn)如下
url = 'https://www.qidian.com/rank/yuepiao?style=1&page=1'
start = time.time() # 開(kāi)始計(jì)時(shí)?
driver = webdriver.Chrome()
driver.get(url)
books = driver.find_elements_by_xpath("http://div[@class='book-img-text']/ul/li")
for book in books:
imglink = 'https:' + book.find_element_by_xpath("./div[1]/a").get_attribute('href')
# 其它小說(shuō)信息的定位提取語(yǔ)句,...
update = book.find_element_by_xpath("./div[2]/p[3]/a").text
print(imglink,title,author,intro,update)
end = time.time() # 結(jié)束計(jì)時(shí)?
print(end-start)
# 18.564752340316772
運(yùn)行結(jié)果如下
可以看到時(shí)間是18.8174s
三、Scrapy
最后是 Scrapy 實(shí)現(xiàn),代碼如下
import scrapy
import time
class QdSpider(scrapy.Spider):
name = 'qd'
allowed_domains = ['qidian.com']
start_urls = ['https://www.qidian.com/rank/yuepiao?style=1&page=1']
def parse(self, response):
start = time.time() # 開(kāi)始計(jì)時(shí)?
books = response.xpath("http://div[@class='book-img-text']/ul/li")
for book in books:
imglink = 'https:' + book.xpath("./div[1]/a/@href").extract_first()
# 其它信息的xpath提取語(yǔ)句,......
update = book.xpath("./div[2]/p[3]/a/text()").extract_first()
print(imglink, title, author, intro, update)
end = time.time() # 結(jié)束計(jì)時(shí)?
print(end - start)
運(yùn)行結(jié)果如下
可以看到運(yùn)行時(shí)間僅僅用了0.016s
四、結(jié)果分析
從代碼量來(lái)看的話:其實(shí)代碼量相差不大,因?yàn)閷?shí)現(xiàn)邏輯比較簡(jiǎn)單。
但從運(yùn)行時(shí)間來(lái)看的話:scrapy 是最快的只花了0.02s不到,selenium 是最慢的,花了將近20s,運(yùn)行效率是 scrapy 的1/1000。不過(guò)scrapy開(kāi)發(fā)、調(diào)試代碼的時(shí)間相比于 requests、selenium 回長(zhǎng)一點(diǎn),
在仔細(xì)研究一下原因
“
requests:requests模擬瀏覽器的請(qǐng)求,將請(qǐng)求到的網(wǎng)頁(yè)內(nèi)容下載下來(lái)以后,并不會(huì)執(zhí)行js代碼。
selenium為什么最慢:首先Selenium是一個(gè)用于Web應(yīng)用程序自動(dòng)化測(cè)試工具,Selenium測(cè)試直接運(yùn)行在瀏覽器中(支持多種瀏覽器,谷歌,火狐等等),模擬用戶進(jìn)行操作,以得到網(wǎng)頁(yè)渲染之后的結(jié)果,selenium解析執(zhí)行了網(wǎng)頁(yè)CSS,js代碼,所以效率較低。”
scrapy框架爬取效率最高:首先同requests一樣,scrapy它也沒(méi)有執(zhí)行網(wǎng)頁(yè)js代碼,但是我們知道scrapy他說(shuō)一個(gè)提取結(jié)構(gòu)性數(shù)據(jù)的應(yīng)用框架,Scrapy使用了Twisted異步網(wǎng)絡(luò)框架,可以加快我們的下載速度,并發(fā)性好,性能較高,所以它的效率最高。
五、補(bǔ)充
通過(guò)上面的簡(jiǎn)單測(cè)試,我們可能會(huì)覺(jué)得selenium效率如此低下,是不是數(shù)據(jù)采集不太常用selenium?只能說(shuō)在能夠爬取到數(shù)據(jù)的前提下,采集效率高的方式才會(huì)作為首選。
所以本文的目的不是為了說(shuō)明不要使用selenium,接下來(lái)我們看看招聘網(wǎng)站--拉勾招聘的頁(yè)面數(shù)據(jù)采集。隨機(jī)選擇一個(gè)崗位java,頁(yè)面如下:
5.1 requests實(shí)現(xiàn)
如果是用 requests 請(qǐng)求數(shù)據(jù)
你會(huì)發(fā)現(xiàn)并沒(méi)有數(shù)據(jù),網(wǎng)頁(yè)做了反爬處理,這時(shí)候selenium就派上用場(chǎng)了,不用分析網(wǎng)站反爬方式,直接模擬用戶請(qǐng)求數(shù)據(jù)(大多數(shù)情況下,也有針對(duì)selenium的反爬手段)
5.2 selenium實(shí)現(xiàn)
如上文所說(shuō),如果是用 requests 或者 scrapy爬蟲(chóng)發(fā)現(xiàn)有反爬措施,可以嘗試selenium,有時(shí)會(huì)異常簡(jiǎn)單
from selenium import webdriver
url = 'https://www.lagou.com/zhaopin/Java/?labelWords=label'
driver = webdriver.Chrome()
driver.get(url)
items = driver.find_elements_by_xpath("http://ul[@class='item_con_list']/li")
print(len(items))
for item in items:
title = item.find_element_by_xpath("./div[1]/div[1]/div[1]/a/h3").text
print(title)
運(yùn)行結(jié)果如下:
很輕松就提取到了頁(yè)面的數(shù)據(jù)!
所以根據(jù)本文的案例分析,如果有爬蟲(chóng)需求時(shí),將方法定格在某一個(gè)方法并非是一個(gè)很好的選擇,大多情況下我們需要根據(jù)對(duì)應(yīng)網(wǎng)站/app的特點(diǎn)以及具體需求,來(lái)綜合判斷,挑選出最合適的爬蟲(chóng)庫(kù)!
-END-
PS:公號(hào)內(nèi)回復(fù)「Python」即可進(jìn)入Python 新手學(xué)習(xí)交流群,一起 100 天計(jì)劃!
老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點(diǎn)一下,如果感覺(jué)文章內(nèi)容不錯(cuò)的話,記得分享朋友圈讓更多的人知道!


【神秘禮包獲取方式】
