python各种数据解析库的速度对比

发布于:2022-12-29 ⋅ 阅读:(247) ⋅ 点赞:(0)

本文以一个小说网站页面为例,提取里面的网址和各章节的名称

将各种数据库解析的速度进行对比,对比对象以下4种方式:

1>>>正则表达式

2>>>BeautifulSoup(忽略其中的css选择器需调用的select方法)

3>>>parsel(包含使用xpath提取和css选择器提取)

4>>>lxml库etree模块XPath

对比速度时, >表示 速度快于 >>表示速度远快于 =表示速度差不多

---------------------

操作思路:

1>>>下载一个小说网页后保存为html格式文件,

2>>>依次用不同的解析数据工具提取所需数据并记录耗时.

3>>>模拟对提取到的数据(url和章节名称)进行字符串操作(网址拼接,章节名替换之类的),记录耗时

4>>>将步骤2的耗时数据与步骤3的耗时数据依次对比

 代码如下

import time
import re
from bs4 import BeautifulSoup
from parsel import Selector
from lxml import etree

def fnc(): #正则提取
    with open("d:/爬虫/1.html",'r',encoding='utf-8') as f:

        href = re.findall(r'<dd><a href="(.*?)">(第.*?)</a>',f.read(),re.S)
        for i in href:
            href = i[0]
            chapter = i[1]

def fnc1(): #parser库css提取
    with open("d:/爬虫/1.html",'r',encoding='utf-8') as f:
        se = Selector(f.read())
        chapter = se.css('.box_con a::text').getall()[16:]
        href = se.css('.box_con a::attr(href)').getall()[22:]
        # href = se.css('.box_con a').re('href="(.*?)">(第.*?)</a>')
        # css结合正则会更加耗时,大约是原来耗时的双倍


def fnc2(): #parser库xpath提取
    with open("d:/爬虫/1.html", 'r', encoding='utf-8') as f:
        se = Selector(f.read())
        chapter = se.xpath('//*[@id="list"]/dl/dd/a/text()').getall()
        href = se.xpath('//*[@id="list"]/dl/dd/a/@href').getall()

def fnc3(): #BeautifulSoup提取
    with open("d:/爬虫/1.html", 'r', encoding='utf-8') as f:
        soup = BeautifulSoup(f.read(),"lxml")
        href = soup.find('div',id ='list').find_all('a')
        for i in href:
            href = i['href']
            chapter = i.text
            
def fnc4(): #lxml库etree模块xpath提取
    with open("d:/爬虫/1.html", 'r', encoding='utf-8') as f:
        html = etree.HTML(f.read())
        chapter = html.xpath('//*[@id="list"]/dl/dd/a/text()')
        href = html.xpath('//*[@id="list"]/dl/dd/a/@href')

def k(): #模拟对提取到的数据,进行字符串操作

    for i in zip(range(10000),range(10000)):
         ii = ''.join(str(i))

if __name__ == '__main__':

    t1 = time.time()
    fnc()
    t2 = time.time()
    print('正则提取数据所需时间',t2-t1)
    fnc1()
    t3 = time.time()
    print('parser解析库采用css选择器提取数据所需时间',t3 - t2) 
    fnc2()
    t4 = time.time()
    print('parser解析库采用xpath选择器提取数据所需时间',t4 - t3)
    fnc3()
    t5 = time.time()
    print('BeautifulSoup解析库提取数据所需时间', t5 - t4)
    fnc4()
    t6 = time.time()
    print('etree使用xptah提取数据所需时间', t6 - t5)
    k()
    t7 = time.time()
    print('模拟从提取到的数据列表取出取出元素所需的时间',t7-t6)
    tim = [(t2-t1), (t3 - t2), (t4 - t3), (t5 - t4), (t6 - t5), (t7-t6)]
    ratio = [([1/_ for _ in tim][5]) / _ for _ in [1/_ for _ in tim]][:-1]
    print(ratio)
    ratio1 = [round(([1/_ for _ in tim][5])/_, 1) for _ in [1 / _ for _ in tim]][:-1]
    print(ratio1) #去掉ratio就不准了

运行结果:

正则提取数据所需时间 0.01699995994567871
parser解析库采用css选择器提取数据所需时间 0.12699675559997559
parser解析库采用xpath选择器提取数据所需时间 0.1300044059753418
BeautifulSoup解析库提取数据所需时间 0.27150392532348633
etree使用xptah提取数据所需时间 0.10106706619262695
模拟从提取到的数据列表取出取出元素所需的时间 0.007998228073120117
[2.1254657644498764, 15.878111306525174, 16.254150892777297, 33.94550928548007, 12.63618207291263]
[2.1, 15.9, 16.3, 33.9, 12.6]

对提取出的数据进行字符串操作耗时最快(如果列表数据元素为10万个,速度是原来的1/10)

正则 >> etree(xpath) = parser(xpath) > parser(css) >> BeautifulSoup

再重复代码15次,比例结果保留2位小数点为:

正则 ps(css) ps(xpath) BS4 etree(xpath)
[2.1,  15.9,  16.3,  33.9,  12.6]   第一次
[2.1,  13.3,  12.6,  41.7,  10.7]
[1.4,  14.7,  14.1,  38.2,  11.9]
[1.1,  12.6,  11.9,  32.8,  9.9]
[2.0,  16.0,  18.8,  43.2,  11.5]
[1.7,  14.4,  16.1,  43.6,  12.9]
[2.0,  13.6,  14.1,  39.6,  13.1]
[1.7,  13.8,  14.9,  50.0,  14.3]
[1.3,  10.7,  11.9,  32.2,  9.9]
[2.4,  11.5,  11.5,  33.4,  13.2]
[2.0,  11.1,  11.5,  38.1,  11.4]   
[2.0,  11.1,  11.5,  38.1,  11.4]
[1.7,  17.9,  17.0,  32.6,  9.9]
[1.9,  13.8,  15.4,  36.1,  10.5]
[1.5,  12.2,  12.2,  31.9,  10.1]
[1.7,  15.3,  14.8,  40.1,  11.4]
[1.9,  13.2,  13.7,  39.9,  10.3]   第十六次

可以看到,结果跟上面的得到的比例结果,正则和BeautifulSoup速度毫无争议

至此,可以宣布:

对于提取网页源代码的数据速度

正则 >>[ etree(xpath),parser(xpath),  parser(css)] >> BeautifulSoup

---------------------

题外话:

由于:

请求一个网页时间得到整个页面数据大概在0.15-0.3秒左右,大部分在0.27,慢的有1秒

所以解析库提取数据的耗时 一般是比 请求网页得到内容的耗时 小的,(更别提存储提取到的数据了)

故涉及阻塞时间 大于提取数据的时间,异步协程会比多线程,多进程更有优势一点;

反之,亦然. 其中细分可见多线程,多进程,异步协程,单线程使用场景