【python单线程、多线程、协程】爬虫案例比较


爬取任务

彼岸图网:4k美女图片,2-10页图片对应的详情页链接

from fake_useragent import UserAgent
import requests
from pyquery import PyQuery as pq
import time

ua = UserAgent(verify_ssl=False, path='D:/Pycharm/fake_useragent.json')

lists = []
start = time.time()


def ua_random():
    headers = {
        'use_agent' : ua.random
    }
    return headers


def scrap_page(url):
    response = requests.get(url=url, headers=ua_random()).text
    doc = pq(response)
    return doc


def scrap_index(page):
    url = f'https://pic.netbian.com/4kmeinv/index_{page}.html'
    return scrap_page(url)


def scrap_link(html):
    links = html('.clearfix li a')
    for link in links.items():
        lists.append('https://pic.netbian.com'+link.attr('href'))


def main():
    # total_page = 5
    for page in range(2, 10):
        html = scrap_index(page)
        scrap_link(html)
    print(lists)
    print(f'总用时:{time.time()-start}')


if __name__ == '__main__':
    main()

输出结果:

总耗时:2.87秒

  • 多线程
from fake_useragent import UserAgent
import requests
from pyquery import PyQuery as pq
import time
from concurrent.futures import ThreadPoolExecutor


ua = UserAgent(verify_ssl=False, path='D:/Pycharm/fake_useragent.json')

lists = []
start = time.time()


def ua_random():
    headers = {
        'use_agent' : ua.random
    }
    return headers


def scrap_page(url):
    response = requests.get(url=url, headers=ua_random()).text
    doc = pq(response)
    return doc


def scrap_index(page):
    url = f'https://pic.netbian.com/4kmeinv/index_{page}.html'
    return scrap_page(url)


def scrap_link(html):
    links = html('.clearfix li a')
    for link in links.items():
        lists.append('https://pic.netbian.com'+link.attr('href'))


def main(page):
    html = scrap_index(page)
    scrap_link(html)
    print(lists)


if __name__ == '__main__':
    page = list(range(2, 10))
    with ThreadPoolExecutor(max_workers=5) as executor:
        executor.map(main, page)
    print('总用时:', time.time()-start)


总耗时:0.86秒

  • 协程
import aiohttp
import asyncio
from fake_useragent import UserAgent
from pyquery import PyQuery as pq
import time


ua = UserAgent(verify_ssl=False, path='D:/Pycharm/fake_useragent.json')

lists = []
start = time.time()


def ua_random():
    headers = {
        'use_agent' : ua.random
    }
    return headers


async def scrape_text(url):
    async with aiohttp.ClientSession(headers=ua_random()) as session:
        async with session.get(url) as response:
            result = await response.text()
            await session.close()
            return result


async def scrap_url(html):
    doc = pq(html)
    links = doc('.clearfix li a')
    for link in links.items():
        lists.append('https://pic.netbian.com' + link.attr('href'))


async def scrap_index(page):
    url = f'https://pic.netbian.com/4kmeinv/index_{page}.html'
    html = await scrape_text(url)
    await scrap_url(html)


async def main():
    scrap_index_tasks = [asyncio.ensure_future(scrap_index(page)) for page in range(2, 10)]
    await asyncio.gather(*scrap_index_tasks)
    print(lists)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    print('总用时:', time.time()-start)


总耗时:0.49秒

对比

单线程 多线程 协程
2.87秒 0.86秒 0.49秒

总结: 一般情况下异步爬虫速度最快,多线程爬虫略慢一点,单线程爬虫速度较慢,必须上一个页面爬取完成才能继续爬取。

**多线程(multithreading)**:是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理或同时多线程处理器。在一个程序中,这些独立运行的程序片段叫作 “线程” (Thread),利用它编程的概念就叫作 “多线程处理”。
**异步(asynchronous)**:为完成某个任务,不同程序单元之间过程中无需通信协调,也能完成任务的方式,不相关的程序单元之间可以是异步的。例如,爬虫下载网页。调度程序调用下载程序后,即可调度其他任务,而无需与该下载任务保持通信以协调行为。不同网页的下载、保存等操作都是无关的,也无需相互通知协调。这些异步操作的完成时刻并不确定。简言之,异步意味着无序。
**协程(coroutine)**,又称微线程、纤程,协程是一种用户态的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此协程能保留上一次调用时的状态,即所有局部状态的一个特定组合,每次过程重入时,就相当于进入上一次调用的状态。协程本质上是个单进程,协程相对于多进程来说,无需线程上下文切换的开销,无需原子操作锁定及同步的开销,编程模型也非常简单。我们可以使用协程来实现异步操作,比如在网络爬虫场景下,我们发出一个请求之后,需要等待一定的时间才能得到响应,但其实在这个等待过程中,程序可以干许多其他的事情,等到响应得到之后才切换回来继续处理,这样可以充分利用CPU 和其他资源,这就是协程的优势。


Author: Polaris119
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Polaris119 !
评论
  TOC