Pythonの爬虫類基礎Ⅳ--マルチコルーチン:食品のカロリーをクロール



爬虫類のベース部Ⅳ

どのような(1)コルーチンです

我々は、長い時間を待つために、その理由が順番に線でプログラム行を実行するためにされているので:私たちは、それは、問題が発生します、我々はクロールしたいデータの数千人がある場合、データは、大規模ではありませんクロールしましたために必要なデータを取得します。

長い時間を登るために爬虫類をクロール大量のデータので、我々は爬虫類で複数のクロールを持つことはできませんか?

我々は、同期した場合(例えばエンドはご飯ご飯を調理し始めることができます)と非同期の爬虫類は、我々の前に学ぶ道であることをウェブクローラのシーンに移行概念(別の例は、その後何の料理を行くんご飯です)同期。

それぞれの爬虫類は、要求を開始し、サーバーが返す応答を待つ必要が、次のステップになります。非常に多くの場合、ネットワークの不安定性に起因し、自身も応答する時間を必要とするサーバーと相まって、爬虫類につながることを待っている多くの時間を無駄にします。これはまた、大量のデータをクロールされ、速度が遅く爬虫類の理由になります。

あなたが取ることができる方法はありません非同期爬虫類ができ、複数のクローラを使用すると、待機時間から削除することはできませんので、お互いに干渉することなくその任務を実施する際に、比較的独立したままにしますか?明らかに、この爬虫類の効率と速度が向上します。

非同期爬虫類の方法を達成するために、そして、使用する必要がある以上コルーチンより


(2)geventライブラリー

どのように非同期爬虫類それ?geventライブラリ(インストールする)、私たちはPythonでコルーチン以上を達成することができます。

今速度に同期および非同期の間のギャップを見て(Baiduの、シーナ、捜狐、テンセント、網易、愛ファンタスティックアート、オオヤマネコ、フェニックスを含む)8つのサイトをクロール:

# -*- coding:utf-8 -*-
import requests,time

start = time.time() #记录程序开始时间

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']
#把8个网站封装成列表


for url in url_list:
    r = requests.get(url)
    print(url,r.status_code) #请求8个网站,打印网址和抓取请求的状态码

end = time.time()
#记录程序结束时间
print(end-start)
#end-start是结束时间减去开始时间,就是最终所花时间。

ローカルで動作した結果は以下のとおりです。

https://www.baidu.com/ 200
https://www.sina.com.cn/ 200
http://www.sohu.com/ 200
https://www.qq.com/ 200
https://www.163.com/ 200
http://www.iqiyi.com/ 200
https://www.tmall.com/ 200
http://www.ifeng.com/ 200
2.2718516063690186

プログラムを実行した後、あなたは同期爬虫類の道が表示されます、されたサイトをクロールに続いて、後に、サーバの応答待ちのウェブサイトを削除するために登る前に(ステータスコード200は、正常な応答を示します)。最初の登りは、サーバの応答として、最初のBaiduのウェブサイトを取った後、すべてが完了するまでクロール例えば、外出先クロールURLは、シーナをとる、というように。


複数のコルーチンをクロール以下を参照してください。

# -*- coding:utf-8 -*-
from gevent import monkey
monkey.patch_all()
import gevent,time,requests

start = time.time()

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']

def crawler(url):
    r = requests.get(url)
    print(url,time.time()-start,r.status_code)

tasks_list = []

for url in url_list:
    task = gevent.spawn(crawler,url)
    tasks_list.append(task)

gevent.joinall(tasks_list)
end = time.time()
print(end-start)

ローカルで動作した結果は以下のとおりです。

https://www.baidu.com/ 0.2156848907470703 200
http://www.iqiyi.com/ 0.2506403923034668 200
http://www.sohu.com/ 0.2510659694671631 200
https://www.163.com/ 0.30031681060791016 200
https://www.qq.com/ 0.347592830657959 200
https://www.tmall.com/ 0.375349760055542 200
https://www.sina.com.cn/ 0.5546746253967285 200
http://www.ifeng.com/ 0.6207404136657715 200
0.6208701133728027

非同期クロール最終多コルーチンに費やされた時間を比較することにより、同期および非同期クロール、爬虫類が速く同期速度より実際の実施形態を示します。実際には、ここでのクロールデータの量は、まだ比較的小さく、直接大きな速度の違いを反映することはできません。登山は多くのデータがある場合は、マルチコルーチンの使用は、より大きな速度の利点となります。

そして時間は、各要求を完了し、するURLリスト内の順序に従っていない来ます。私はこのコードを実行する場合、例えば、その百度に最初のクロールは、iQIYI代わりのsiNAを行いました。


(3)複数のコルーチンを使用して

話すようにステップバイステップ(╹▽╹

1.プログラムは、マルチのコラボレーションを実行するように設定されています

from gevent import monkey
#从gevent库里导入monkey模块。

monkey.patch_all()
#monkey.patch_all()能把程序变成协作式运行,就是可以帮助程序实现异步。

import gevent,time,requests
#导入gevent、time、requests。

geventライブラリ導入monkey非同期アプリケーションプログラムに変換することができ、モジュール。monkey.patch_all()その役割は、時々ポップアップ同じ「脆弱性パッチを適用または更新を使用するかどうかを、」ちょうどあなたのコンピュータのようなものです。これは、プログラムにパッチ、プログラムがあることが判明する非同期モードではなく、同期モード。また「と呼ばれる猿のパッチ。」

注:あなたが他のライブラリとモジュールをインポートする前に、最初の猿インポートモジュールが入って来て、実行monkey.patch_all()。


クロール機能を定義する2

start = time.time() #记录程序开始时间。

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']
#把8个网站封装成列表。

def crawler(url):
#定义一个crawler()函数。
    r = requests.get(url)
    #用requests.get()函数爬取网站。
    print(url,time.time()-start,r.status_code)
    #打印网址、请求运行时间、状态码。

それは定義しcrawler、この関数が呼び出される限り、それは[で実行されるよう、機能をrequests.get()サイトをクロール]と[時間を実行するためのプリントURL要求、ステータスコード]これら二つのタスク。


3.()gevent.spawnでタスクを作成します

tasks_list = [ ]
#创建空的任务列表。

for url in url_list:
#遍历url_list。
    task = gevent.spawn(crawler,url)
    #用gevent.spawn()函数创建任务。
    tasks_list.append(task)
    #往任务列表添加任务。
gevent.joinall(tasks_list)
#调用gevent库里的joinall方法,能启动执行任务列表里所有的任务,就是让爬虫开始爬取网站。
end = time.time()
#记录程序结束时间。
print(end-start)
#打印程序最终所需时间。

コードの6行上記task = gevent.spawn(crawler,url)ので、geventハンドルのみがタスク・オブジェクトをgevent直接、正常な機能を呼び出すことができないことが必要ようにgevent.spawn()するタスク・オブジェクトを作成します

:ことに留意すべきであるgevent.spawn()ために必要なパラメータ関数名が呼び出されると、関数のパラメータ例えば、gevent.spawn(crawler,url)それは、エグゼクティブ作成することでcrawler、タスク機能をクローラ関数名と、独自のパラメータのURLのパラメータ。

このコード行gevent.joinall(tasks_list)を実行tasks_listするすべてのタスクのこのタスクリストには、クロールを開始します。

最後に、時間を印刷します。


(4)キューとコルーチンとモジュール

私達は私達がちょうど学んだgevent文法で、8つのサイトが、1000件のサイトよりも上昇している場合、私たちはできることをgevent.spawn()1000年クロールタスクを作成し、gevent.joinall()1000年のミッションを実行します。しかし、悪質なリクエストのこの方法は、サーバがサイトを長持ちします!

その後、我々は5つのタスクにのみ作成することができますが、各タスクには、200のウェブサイトをクロール?このように書きます:

from gevent import monkey
monkey.patch_all()
import gevent,time,requests

start = time.time()
url_list = [ 
    #假设有1000个网址 
]

def crawler(url_list): #定义一个crawler()函数。参数为url列表
    for url in url_list:
        r = requests.get(url)
        print(url,time.time()-start,r.status_code)

tasks_list = [ ]
#创建空的任务列表。
for i in range(5):
    task = gevent.spawn(crawler,url_list[i*200:(i+1)*200])
    #用gevent.spawn()函数创建5个任务。
    tasks_list.append(task)
    #往任务列表添加任务。

gevent.joinall(tasks_list)
end = time.time()
print(end-start)

申し訳ありませんがさえて、と言ってgevent.spawn()、これらの5つのタスク間で非同期に実行されますが、各タスクは(200件のサイトをクロール)内部が同期されているものの5の作成は、200のウェブサイトのタスクをクロール実行されました。

この手段:他のタスクは、200社のウェブサイトをクロール完了している場合でも、実装のプロセスにタスクがある場合は、それがサイトをクロールすることであるが、応答を待っている、それはまだ200サイトのクロールを完了することはできません。


あなたが、解決するためにキューを使用することができqueue、タスクがきちんとしたキューになって、キューが空になるまで、タスクが終了処理となりますので、コルーチンが出てタスクを実行するためにキューから抽出することができ、タスクを格納するモジュール。

使い方queue8つのサイトをつかむために、まだ、モジュールおよび協会の過程で、例えば、注を参照してください。

from gevent import monkey
monkey.patch_all()
import gevent,time,requests
from gevent.queue import Queue #从gevent库里导入队列
#因为gevent库里就带有queue,所以我们用【from gevent.queue import Queue】就能把queue模块导入。

start = time.time()

url_list = ['https://www.baidu.com/',
'https://www.sina.com.cn/',
'http://www.sohu.com/',
'https://www.qq.com/',
'https://www.163.com/',
'http://www.iqiyi.com/',
'https://www.tmall.com/',
'http://www.ifeng.com/']

work = Queue() #创建队列对象,并赋值给work。
for url in url_list:
    work.put_nowait(url) #用put_nowait()函数可以把网址都放进队列里。

def crawler():
    while not work.empty(): #当队列不是空的时候,就执行下面的程序。
        url = work.get_nowait() #用get_nowait()函数可以把队列里的网址取出。
        r = requests.get(url) #用requests.get()函数抓取网址。
        print(url,work.qsize(),r.status_code) #打印网址、队列长度、抓取请求的状态码。

tasks_list  = [ ] #创建空的任务列表

for x in range(2): #相当于创建了2个爬虫
    task = gevent.spawn(crawler) #用gevent.spawn()函数创建执行crawler()函数的任务。
    tasks_list.append(task) #往任务列表添加任务。
gevent.joinall(tasks_list) #用gevent.joinall方法,执行任务列表里的所有任务,就是让爬虫开始爬取网站。
end = time.time()
print(end-start)

ローカルの結果を操作します:

https://www.baidu.com/ 6 200
http://www.sohu.com/ 5 200
https://www.sina.com.cn/ 4 200
https://www.163.com/ 3 200
https://www.qq.com/ 2 200
http://www.iqiyi.com/ 1 200
http://www.ifeng.com/ 0 200
https://www.tmall.com/ 0 200
1.2389874458312988

数字の下にリストされているWebサイトは、この時点では、そのようである最初のURLの数6、後のようキューに残されたタスクの数に6つのタスクを左キュークロールを他のURLを参照してください。

私たちは、同等の持つ非同期爬虫類クロール2を作成する(8匹の爬虫類の同等の非同期クロール、ウェブサイトをクロールすべての爬虫類を作成することができ、無駄な8つのサイトの前にキューをクロール)。彼らは、クロールタスクを実行する、URLキューから削除されます。Webサイトが削除爬虫類したら、別の爬虫類未満がかかります、それは次のURLを奪うだろう。すべてのURLが削除されるまで、キューが空である、爬虫類は動作を停止しました。


(5)例:クロールカロリー

あなたはこの中で、マルチコルーチンの食品のカロリー、URLのクロールミントネットワークを練習することができhttp://www.boohee.com/food/

食品の各カテゴリーの最初の2つの、5つのカテゴリーの前にクロール[食品の名称、熱、詳細リンク]、ローカルに保存されたデータ。

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
from gevent import monkey
monkey.patch_all() #让程序变成异步模式。
import gevent,requests, openpyxl, time
from gevent.queue import Queue
from bs4 import BeautifulSoup

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
def getfood(url): #获取url页面的食物信息
    foodlist = []
    res = requests.get(url,headers=headers)
    bs4 = BeautifulSoup(res.text, 'html.parser')
    items = bs4.find_all('li', class_='clearfix')
    for item in items:
        detail = item.find('div', class_='text-box')
        name = detail.find('a')['title']
        href = 'http://www.boohee.com'+detail.find('a')['href']
        heat = detail.find('p').text
        # print(name,href,heat)
        foodlist.append([name, heat, href])
    return foodlist

def savefood(items): #储存食物信息
    for item in items:
        sheet.append(item)

#存入excel
wb = openpyxl.Workbook()
sheet = wb.active
sheet.title = 'food heat'
sheet['A1'] = '食物'
sheet['B1'] = '热量'
sheet['C1'] = '详情链接'

work = Queue() #构造url队列
url = 'http://www.boohee.com/food/group/{type}?page={page}'
for group in range(1,6): #前五个分类
    for page in range(1,3): #前两页
        work.put_nowait(url.format(type=group, page=page))

def crawler():
    while not work.empty():
        list1 = getfood(work.get_nowait())
        savefood(list1)

task_list = []
for i in range(5): #创建5个爬虫
    task = gevent.spawn(crawler)#用gevent.spawn()函数创建执行crawler()函数的任务。
    task_list.append(task)#往任务列表添加任务

workstart = time.time()
gevent.joinall(task_list)
#用gevent.joinall方法,启动协程,执行任务列表里的所有任务,让爬虫开始爬取网站。
workend = time.time()
print('操作完成,用时:'+str(workend-workstart))

wb.save('food heat.xlsx')



--------誰もが人生について不平を言っていることは容易ではありませんが、生活のために静かに難しいです--------

公開された16元の記事 ウォンの賞賛113 ビュー4891

おすすめ

転載: blog.csdn.net/qq_43280818/article/details/97494144