欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python 爬蟲性能相關(guān)總結(jié)

 更新時(shí)間:2020年08月03日 10:45:06   作者:syncd  
這篇文章主要介紹了Python 爬蟲性能的相關(guān)資料,文中講解非常詳細(xì),幫助大家更好的理解和學(xué)習(xí)爬蟲,感興趣的朋友可以了解下

這里我們通過(guò)請(qǐng)求網(wǎng)頁(yè)例子來(lái)一步步理解爬蟲性能

當(dāng)我們有一個(gè)列表存放了一些url需要我們獲取相關(guān)數(shù)據(jù),我們首先想到的是循環(huán)

簡(jiǎn)單的循環(huán)串行

這一種方法相對(duì)來(lái)說(shuō)是最慢的,因?yàn)橐粋€(gè)一個(gè)循環(huán),耗時(shí)是最長(zhǎng)的,是所有的時(shí)間總和
代碼如下:

import requests

url_list = [
  'http://www.baidu.com',
  'http://www.pythonsite.com',
  'http://www.cnblogs.com/'
]

for url in url_list:
  result = requests.get(url)
  print(result.text)

通過(guò)線程池

通過(guò)線程池的方式訪問,這樣整體的耗時(shí)是所有連接里耗時(shí)最久的那個(gè),相對(duì)循環(huán)來(lái)說(shuō)快了很多

import requests
from concurrent.futures import ThreadPoolExecutor

def fetch_request(url):
  result = requests.get(url)
  print(result.text)

url_list = [
  'http://www.baidu.com',
  'http://www.bing.com',
  'http://www.cnblogs.com/'
]
pool = ThreadPoolExecutor(10)

for url in url_list:
  #去線程池中獲取一個(gè)線程,線程去執(zhí)行fetch_request方法
  pool.submit(fetch_request,url)

pool.shutdown(True)

線程池+回調(diào)函數(shù)

這里定義了一個(gè)回調(diào)函數(shù)callback

from concurrent.futures import ThreadPoolExecutor
import requests


def fetch_async(url):
  response = requests.get(url)

  return response


def callback(future):
  print(future.result().text)


url_list = [
  'http://www.baidu.com',
  'http://www.bing.com',
  'http://www.cnblogs.com/'
]

pool = ThreadPoolExecutor(5)

for url in url_list:
  v = pool.submit(fetch_async,url)
  #這里調(diào)用回調(diào)函數(shù)
  v.add_done_callback(callback)

pool.shutdown()

通過(guò)進(jìn)程池

通過(guò)進(jìn)程池的方式訪問,同樣的也是取決于耗時(shí)最長(zhǎng)的,但是相對(duì)于線程來(lái)說(shuō),進(jìn)程需要耗費(fèi)更多的資源,同時(shí)這里是訪問url時(shí)IO操作,所以這里線程池比進(jìn)程池更好

import requests
from concurrent.futures import ProcessPoolExecutor

def fetch_request(url):
  result = requests.get(url)
  print(result.text)

url_list = [
  'http://www.baidu.com',
  'http://www.bing.com',
  'http://www.cnblogs.com/'
]
pool = ProcessPoolExecutor(10)

for url in url_list:
  #去進(jìn)程池中獲取一個(gè)線程,子進(jìn)程程去執(zhí)行fetch_request方法
  pool.submit(fetch_request,url)

pool.shutdown(True)

進(jìn)程池+回調(diào)函數(shù)

這種方式和線程+回調(diào)函數(shù)的效果是一樣的,相對(duì)來(lái)說(shuō)開進(jìn)程比開線程浪費(fèi)資源

from concurrent.futures import ProcessPoolExecutor
import requests


def fetch_async(url):
  response = requests.get(url)

  return response


def callback(future):
  print(future.result().text)


url_list = [
  'http://www.baidu.com',
  'http://www.bing.com',
  'http://www.cnblogs.com/'
]

pool = ProcessPoolExecutor(5)

for url in url_list:
  v = pool.submit(fetch_async, url)
  # 這里調(diào)用回調(diào)函數(shù)
  v.add_done_callback(callback)

pool.shutdown()

主流的單線程實(shí)現(xiàn)并發(fā)的幾種方式

  1. asyncio
  2. gevent
  3. Twisted
  4. Tornado

下面分別是這四種代碼的實(shí)現(xiàn)例子:

asyncio例子1:

import asyncio


@asyncio.coroutine #通過(guò)這個(gè)裝飾器裝飾
def func1():
  print('before...func1......')
  # 這里必須用yield from,并且這里必須是asyncio.sleep不能是time.sleep
  yield from asyncio.sleep(2)
  print('end...func1......')


tasks = [func1(), func1()]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()

上述的效果是同時(shí)會(huì)打印兩個(gè)before的內(nèi)容,然后等待2秒打印end內(nèi)容
這里asyncio并沒有提供我們發(fā)送http請(qǐng)求的方法,但是我們可以在yield from這里構(gòu)造http請(qǐng)求的方法。

asyncio例子2:

import asyncio


@asyncio.coroutine
def fetch_async(host, url='/'):
  print("----",host, url)
  reader, writer = yield from asyncio.open_connection(host, 80)

  #構(gòu)造請(qǐng)求頭內(nèi)容
  request_header_content = """GET %s HTTP/1.0\r\nHost: %s\r\n\r\n""" % (url, host,)
  request_header_content = bytes(request_header_content, encoding='utf-8')
  #發(fā)送請(qǐng)求
  writer.write(request_header_content)
  yield from writer.drain()
  text = yield from reader.read()
  print(host, url, text)
  writer.close()

tasks = [
  fetch_async('www.cnblogs.com', '/zhaof/'),
  fetch_async('dig.chouti.com', '/pic/show?nid=4073644713430508&lid=10273091')
]

loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(*tasks))
loop.close()

asyncio + aiohttp 代碼例子:

import aiohttp
import asyncio


@asyncio.coroutine
def fetch_async(url):
  print(url)
  response = yield from aiohttp.request('GET', url)
  print(url, response)
  response.close()


tasks = [fetch_async('http://baidu.com/'), fetch_async('http://www.chouti.com/')]

event_loop = asyncio.get_event_loop()
results = event_loop.run_until_complete(asyncio.gather(*tasks))
event_loop.close()

asyncio+requests代碼例子

import asyncio
import requests


@asyncio.coroutine
def fetch_async(func, *args):
  loop = asyncio.get_event_loop()
  future = loop.run_in_executor(None, func, *args)
  response = yield from future
  print(response.url, response.content)


tasks = [
  fetch_async(requests.get, 'http://www.cnblogs.com/wupeiqi/'),
  fetch_async(requests.get, 'http://dig.chouti.com/pic/show?nid=4073644713430508&lid=10273091')
]

loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(*tasks))
loop.close()

gevent+requests代碼例子

import gevent

import requests
from gevent import monkey

monkey.patch_all()


def fetch_async(method, url, req_kwargs):
  print(method, url, req_kwargs)
  response = requests.request(method=method, url=url, **req_kwargs)
  print(response.url, response.content)

# ##### 發(fā)送請(qǐng)求 #####
gevent.joinall([
  gevent.spawn(fetch_async, method='get', url='https://www.python.org/', req_kwargs={}),
  gevent.spawn(fetch_async, method='get', url='https://www.yahoo.com/', req_kwargs={}),
  gevent.spawn(fetch_async, method='get', url='https://github.com/', req_kwargs={}),
])

# ##### 發(fā)送請(qǐng)求(協(xié)程池控制最大協(xié)程數(shù)量) #####
# from gevent.pool import Pool
# pool = Pool(None)
# gevent.joinall([
#   pool.spawn(fetch_async, method='get', url='https://www.python.org/', req_kwargs={}),
#   pool.spawn(fetch_async, method='get', url='https://www.yahoo.com/', req_kwargs={}),
#   pool.spawn(fetch_async, method='get', url='https://www.github.com/', req_kwargs={}),
# ])

grequests代碼例子
這個(gè)是講requests+gevent進(jìn)行了封裝

import grequests


request_list = [
  grequests.get('http://httpbin.org/delay/1', timeout=0.001),
  grequests.get('http://fakedomain/'),
  grequests.get('http://httpbin.org/status/500')
]


# ##### 執(zhí)行并獲取響應(yīng)列表 #####
# response_list = grequests.map(request_list)
# print(response_list)


# ##### 執(zhí)行并獲取響應(yīng)列表(處理異常) #####
# def exception_handler(request, exception):
# print(request,exception)
#   print("Request failed")

# response_list = grequests.map(request_list, exception_handler=exception_handler)
# print(response_list)

twisted代碼例子

#getPage相當(dāng)于requets模塊,defer特殊的返回值,rector是做事件循環(huán)
from twisted.web.client import getPage, defer
from twisted.internet import reactor

def all_done(arg):
  reactor.stop()

def callback(contents):
  print(contents)

deferred_list = []

url_list = ['http://www.bing.com', 'http://www.baidu.com', ]
for url in url_list:
  deferred = getPage(bytes(url, encoding='utf8'))
  deferred.addCallback(callback)
  deferred_list.append(deferred)
#這里就是進(jìn)就行一種檢測(cè),判斷所有的請(qǐng)求知否執(zhí)行完畢
dlist = defer.DeferredList(deferred_list)
dlist.addBoth(all_done)

reactor.run()

tornado代碼例子

from tornado.httpclient import AsyncHTTPClient
from tornado.httpclient import HTTPRequest
from tornado import ioloop


def handle_response(response):
  """
  處理返回值內(nèi)容(需要維護(hù)計(jì)數(shù)器,來(lái)停止IO循環(huán)),調(diào)用 ioloop.IOLoop.current().stop()
  :param response: 
  :return: 
  """
  if response.error:
    print("Error:", response.error)
  else:
    print(response.body)


def func():
  url_list = [
    'http://www.baidu.com',
    'http://www.bing.com',
  ]
  for url in url_list:
    print(url)
    http_client = AsyncHTTPClient()
    http_client.fetch(HTTPRequest(url), handle_response)


ioloop.IOLoop.current().add_callback(func)
ioloop.IOLoop.current().start()

以上就是Python 爬蟲性能相關(guān)總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Python 爬蟲性能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python實(shí)現(xiàn)把多維數(shù)組展開成DataFrame

    Python實(shí)現(xiàn)把多維數(shù)組展開成DataFrame

    今天小編就為大家分享一篇Python實(shí)現(xiàn)把多維數(shù)組展開成DataFrame,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11
  • python爬蟲使用cookie登錄詳解

    python爬蟲使用cookie登錄詳解

    這篇文章主要介紹了python爬蟲使用cookie登錄詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2017-12-12
  • python常用庫(kù)之NumPy和sklearn入門

    python常用庫(kù)之NumPy和sklearn入門

    這篇文章主要介紹了python常用庫(kù)之NumPy和sklearn入門,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Python?pandas按行、按列遍歷DataFrame的幾種方式

    Python?pandas按行、按列遍歷DataFrame的幾種方式

    在python的DataFrame中,因?yàn)閿?shù)據(jù)中可以有多個(gè)行和列,而且每行代表一個(gè)數(shù)據(jù)樣本,我們可以將DataFrame看作數(shù)據(jù)表,那你知道如何按照數(shù)據(jù)表中的行遍歷嗎,下面這篇文章主要給大家介紹了關(guān)于Python?pandas按行、按列遍歷DataFrame的幾種方式,需要的朋友可以參考下
    2022-09-09
  • python 中字典嵌套列表的方法

    python 中字典嵌套列表的方法

    今天小編就為大家分享一篇python 中字典嵌套列表的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • Python自動(dòng)操作Excel文件的方法詳解

    Python自動(dòng)操作Excel文件的方法詳解

    大家平時(shí)在工作與學(xué)習(xí)中都會(huì)操作到Excel文件格式,特別是很多數(shù)據(jù)的時(shí)候,靠人力去識(shí)別操作非常容易出錯(cuò)。今天就帶大家用Python來(lái)處理Excel文件,讓你成為一個(gè)別人眼中的秀兒
    2022-05-05
  • Python迭代器和生成器介紹

    Python迭代器和生成器介紹

    這篇文章主要介紹了Python迭代器和生成器介紹,本文分別用代碼實(shí)例講解了Python的迭代器和生成器,需要的朋友可以參考下
    2015-03-03
  • Python腳本實(shí)現(xiàn)網(wǎng)卡流量監(jiān)控

    Python腳本實(shí)現(xiàn)網(wǎng)卡流量監(jiān)控

    這篇文章主要介紹了Python腳本實(shí)現(xiàn)網(wǎng)卡流量監(jiān)控,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2015-02-02
  • python向xls寫入數(shù)據(jù)(包括合并,邊框,對(duì)齊,列寬)

    python向xls寫入數(shù)據(jù)(包括合并,邊框,對(duì)齊,列寬)

    這篇文章主要介紹了python向xls寫入數(shù)據(jù)(包括合并,邊框,對(duì)齊,列寬),幫助大家更好的利用python處理表格,感興趣的朋友可以了解下
    2021-02-02
  • Pandas直接讀取sql腳本的方法

    Pandas直接讀取sql腳本的方法

    這篇文章主要介紹了Pandas直接讀取sql腳本的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01

最新評(píng)論