成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

python:利用asyncio進行快速抓取

開發 后端 開發工具
web數據抓取是一個經常在python的討論中出現的主題。有很多方法可以用來進行web數據抓取,然而其中好像并沒有一個最好的辦法。有一些如scrapy這樣十分成熟的框架,更多的則是像mechanize這樣的輕量級庫。DIY自己的解決方案同樣十分流行:你可以使用requests、beautifulsoup或者pyquery來實現。

web數據抓取是一個經常在python的討論中出現的主題。有很多方法可以用來進行web數據抓取,然而其中好像并沒有一個***的辦法。有一些如scrapy這樣十分成熟的框架,更多的則是像mechanize這樣的輕量級庫。DIY自己的解決方案同樣十分流行:你可以使用requestsbeautifulsoup或者pyquery來實現。

方法如此多樣的原因在于,數據“抓取”實際上包括很多問題:你不需要使用相同的工具從成千上萬的頁面中抓取數據,同時使一些Web工作流自動化(例如填一些表單然后取回數據)。我喜歡DIY的原因在于其靈活性,但是卻不適合用來做大量數據的抓取,因為需要請求同步,所以大量的請求意味著你不得不等待很長時間。

在本文中,我將會為你展示一個基于新的異步庫(aiohttp)的請求的代替品。我使用它寫了一些速度的確很快的小數據抓取器,下面我將會為你演示是如何做到的。

asyncio的基本概念

asyncio是在python3.4中被引進的異步IO庫。你也可以通過python3.3的pypi來安裝它。它相當的復雜,而且我不會介紹太多的細節。相反,我將會解釋你需要知道些什么,以利用它來寫異步的代碼。

簡而言之,有兩件事情你需要知道:協同程序和事件循環。協同程序像是方法,但是它們可以在代碼中的特定點暫停和繼續。當在等待一個IO(比如一個HTTP請求),同時執行另一個請求的時候,可以用來暫停一個協同程序。我們使用關鍵字yield from來設定一個狀態,表明我們需要一個協同程序的返回值。而事件循環則被用來安排協同程序的執行。

關于asyncio還有很多很多,但是以上是我們到目前為止需要知道的。可能你還有些不清楚,那么讓我們來看一些代碼吧。

aiohttp

aiohttp是一個利用asyncio的庫,它的API看起來很像請求的API。到目前為止,相關文檔還不健全。但是這里有一些非常有用的例子。我們將會演示它的基本用法。

首先,我們會定義一個協同程序用來獲取頁面,并打印出來。我們使用 asyncio.coroutine將一個方法裝飾成一個協同程序。aiohttp.request是一個協同程序,所以它是一個可讀方法,我們需要使用yield from來調用它們。除了這些,下面的代碼看起來相當直觀:

  1. @asyncio.coroutine  
  2. def print_page(url):  
  3.     response = yield from aiohttp.request('GET', url)  
  4.     body = yield from response.read_and_close(decode=True)  
  5.     print(body) 

如你所見,我們可以使用yield from從另一個協同程序中調用一個協同程序。為了從同步代碼中調用一個協同程序,我們需要一個事件循環。我們可以通過asyncio.get_event_loop()得到一個標準的事件循環,之后使用它的run_until_complete()方法來運行協同程序。所以,為了使之前的協同程序運行,我們只需要做下面的步驟:

  1. loop = asyncio.get_event_loop()  
  2. loop.run_until_complete(print_page('http://example.com')) 

一個有用的方法是asyncio.wait,通過它可以獲取一個協同程序的列表,同時返回一個將它們全包括在內的單獨的協同程序,所以我們可以這樣寫:

  1. loop.run_until_complete(asyncio.wait([print_page('http://example.com/foo'),  
  2.                                       print_page('http://example.com/bar')])) 

另一個是asyncio.as_completed,通過它可以獲取一個協同程序的列表,同時返回一個按完成順序生成協同程序的迭代器,因此當你用它迭代時,會盡快得到每個可用的結果。

數據抓取

現在我們知道了如何做異步HTTP請求,因此我們可以來寫一個數據抓取器了。我們僅僅還需要一些工具來讀取html頁面,我使用了beautifulsoup來做這個事情,其余的像 pyquerylxml也可以實現。

在這個例子中,我們會寫一個小數據抓取器來從海盜灣抓取一些linux distributions的torrent 鏈路(海盜灣(英語:The Pirate Bay,縮寫:TPB)是一個專門存儲、分類及搜索Bittorrent種子文件的網站,并自稱“世界***的BitTorrent tracker(BT種子服務器)”,提供的BT種子除了有自由版權的收集外,也有不少被著作人聲稱擁有版權的音頻、視頻、應用軟件與電子游戲等,為網絡分享與下載的重要網站之一–譯者注來自維基百科)

首先,需要一個輔助協同程序來獲取請求:

  1. @asyncio.coroutine  
  2. def get(*args, **kwargs):  
  3.     response = yield from aiohttp.request('GET', *args, **kwargs)  
  4.     return (yield from response.read_and_close(decode=True)) 

解析部分。本文并非介紹beautifulsoup的,所以這部分我會簡寫:我們獲取了這個頁面的***個磁鏈。

  1. def first_magnet(page):  
  2.     soup = bs4.BeautifulSoup(page)  
  3.     a = soup.find('a', title='Download this torrent using magnet')  
  4.     return a['href'

在這個協同程序中,url的結果通過種子的數量進行排序,所以排名***的結果實際上是種子最多的:

  1. @asyncio.coroutine  
  2. def print_magnet(query):  
  3.     url = 'http://thepiratebay.se/search/{}/0/7/0'.format(query)  
  4.     page = yield from get(url, compress=True)  
  5.     magnet = first_magnet(page)  
  6.     print('{}: {}'.format(query, magnet)) 

***,用下面的代碼來調用以上所有的方法。

  1. distros = ['archlinux''ubuntu''debian']  
  2. loop = asyncio.get_event_loop()  
  3. f = asyncio.wait([print_magnet(d) for d in distros])  
  4. loop.run_until_complete(f) 

#p#

結論

好了,現在我們來到了這個部分。你有了一個異步工作的小抓取器。這意味著多個頁面可以同時被下載,所以這個例子要比使用請求的相同代碼快3倍。現在你應該可以用相同的方法寫出你自己的抓取器了。

你可以在這里找到生成的代碼,也包括一些額外的建議。

你一旦熟悉了這一切,我建議你看一看asyncio的文檔和aiohttp的范例,這些都能告訴你 asyncio擁有怎樣的潛力。

這種方法(事實上是所有手動的方法)的一個局限在于,沒有一個獨立的庫可以用來處理表單。機械化的方法擁有很多輔助工具,這使得提交表單變得十分簡單,但是如果你不使用它們,你將不得不自己去處理這些事情。這可能會導致一些bug的出現,所以同時我可能會寫一個這樣的庫(不過目前為止無需為此擔心)。

額外的建議:不要敲打服務器

同時做3個請求很酷,但是同時做5000個就不那么好玩了。如果你打算同時做太多的請求,鏈接有可能會斷掉。你甚至有可能會被禁止鏈接網絡。

為了避免這些,你可以使用semaphore。這是一個可以被用來限制同時工作的協同程序數量的同步工具。我們只需要在建立循環之前創建一個semaphore ,同時把我們希望允許的同時請求的數量作為參數傳給它既可:

  1. sem = asyncio.Semaphore(5

然后,我們只需要將下面

  1. page = yield from get(url, compress=True)  

替換成被semaphore 保護的同樣的東西。

  1. with (yield from sem):  
  2.     page = yield from get(url, compress=True

這就可以保證同時最多有5個請求會被處理。

額外建議:進度條

這個東東是免費的哦:tqdm是一個用來生成進度條的優秀的庫。這個協同程序就像asyncio.wait一樣工作,不過會顯示一個代表完成度的進度條。

  1. @asyncio.coroutine  
  2. def wait_with_progress(coros):  
  3.     for f in tqdm.tqdm(asyncio.as_completed(coros), total=len(coros)):  
  4.         yield from f 

原文鏈接: compiletoi   翻譯: 伯樂在線 - 慕容老匹夫

譯文鏈接: http://blog.jobbole.com/63897/

責任編輯:林師授 來源: 伯樂在線
相關推薦

2025-01-13 08:20:00

Python數據抓取

2023-11-24 11:20:20

2017-08-02 15:00:12

PythonAsyncio異步編程

2020-02-21 08:00:00

Pythonasyncio編程語言

2021-10-16 17:56:57

Python桌面應用

2017-05-05 08:44:24

PythonAsyncio異步編程

2017-09-05 08:08:37

asyncio程序多線程

2024-11-20 10:00:00

Python文件讀寫

2023-07-14 15:10:17

PythonAsyncIO庫

2014-05-13 14:27:55

2024-11-13 15:22:36

Python列表切片

2017-05-08 15:47:06

2020-06-05 14:29:07

PythonPandas數據分析

2021-04-29 00:20:21

Python親和性分析

2011-03-04 09:09:07

BlueJ

2017-08-16 10:12:10

CNN網絡數據

2009-06-15 17:45:20

LINQ分組統計

2024-06-05 08:16:32

2024-03-28 14:40:55

2012-01-18 10:47:38

ibmdw
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲国产一区二区在线 | av看片| 国产精品国产三级国产aⅴ无密码 | 精品av| 爱高潮www亚洲精品 中文字幕免费视频 | 日韩免费高清视频 | 99久久精品免费看国产四区 | 久久999| 亚洲区中文字幕 | 成人在线观看免费爱爱 | 国产成人一区二区三区 | 精品欧美乱码久久久久久 | 欧美老少妇一级特黄一片 | 亚洲欧美日韩精品久久亚洲区 | av一级在线观看 | 国产欧美精品区一区二区三区 | 国产91在线播放 | 日韩视频一区二区 | 国产成人精品久久二区二区91 | 国产免费一区二区三区免费视频 | 精品国产乱码久久久 | 亚洲三级av | 羞羞的视频在线看 | 亚洲精品在线免费观看视频 | 黄片毛片免费观看 | 无码一区二区三区视频 | 一区二区三区在线电影 | 亚洲在线免费观看 | 黄视频免费 | 亚洲一区在线免费观看 | 亚洲国产精品成人久久久 | 一二三区视频 | 一本一道久久a久久精品综合 | 欧美日韩在线一区二区 | 亚洲天天干 | 亚洲精品视频在线观看视频 | 国产精品毛片一区二区在线看 | 欧美午夜视频 | 国产精品久久久久久久久久不蜜臀 | 亚欧精品| 亚洲精品久久久蜜桃 |