国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - 在Python3中使用asyncio庫進行快速數(shù)據(jù)抓取的教程

在Python3中使用asyncio庫進行快速數(shù)據(jù)抓取的教程

2020-05-28 10:07Georges Dubus Python

這篇文章主要介紹了在Python3中使用asyncio進行快速數(shù)據(jù)抓取,asyncio是一個異步IO庫,運行效率較高,需要的朋友可以參考下

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

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

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

asyncio的基本概念
asyncio是在python3.4中被引進的異步IO庫。你也可以通過python3.3的pypi來安裝它。它相當(dāng)?shù)膹?fù)雜,而且我不會介紹太多的細(xì)節(jié)。相反,我將會解釋你需要知道些什么,以利用它來寫異步的代碼。

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

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

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

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

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

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

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

一個有用的方法是asyncio.wait,通過它可以獲取一個協(xié)同程序的列表,同時返回一個將它們?nèi)ㄔ趦?nèi)的單獨的協(xié)同程序,所以我們可以這樣寫:
 

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

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

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

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

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

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

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

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

在這個協(xié)同程序中,url的結(jié)果通過種子的數(shù)量進行排序,所以排名第一的結(jié)果實際上是種子最多的:
 

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

最后,用下面的代碼來調(diào)用以上所有的方法。
 

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

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

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

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

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

額外的建議:不要敲打服務(wù)器
同時做3個請求很酷,但是同時做5000個就不那么好玩了。如果你打算同時做太多的請求,鏈接有可能會斷掉。你甚至有可能會被禁止鏈接網(wǎng)絡(luò)。

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

?
1
sem = asyncio.Semaphore(5)

然后,我們只需要將下面
 

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

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

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

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

額外建議:進度條
這個東東是免費的哦:tqdm是一個用來生成進度條的優(yōu)秀的庫。這個協(xié)同程序就像asyncio.wait一樣工作,不過會顯示一個代表完成度的進度條。
 

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 中文字幕在线一区 | 日本久久精品视频 | 久久亚洲二区 | 自拍偷拍在线视频 | 在线国产精品一区 | 精品一区二区三区免费视频 | 国产剧情一区 | 国产精品毛片一区二区 | 性色综合| 玖玖精品| 国产99久久精品一区二区永久免费 | 夜夜草视频 | 欧美成人免费 | 国产精品福利电影网 | 亚洲精品电影网在线观看 | 久久久久亚洲精品 | 国产乱码精品一区二区三区中文 | 欧美国产一区二区三区 | 国产aaaaav久久久一区二区 | 久久99久久99精品免视看婷婷 | 日韩激情一级 | 亚洲国产一区二区三区在线播放 | 久久av综合 | 欧美在线高清 | 激情综合五月 | 高清视频一区二区三区 | 自拍偷拍中文字幕 | 日本黄a三级三级三级 | 久久国产精品亚洲 | 91免费观看视频 | 欧美a在线 | 精品久 | 久久久久久久国产精品 | 久久天天躁狠狠躁夜夜躁2014 | 精品中文一区 | 国产成人精品一区二区三区福利 | 一级电影免费看 | 五月婷婷激情网 | 国产精品久久久久久久一区探花 | 久久久综合色 | 免费av电影观看 |