爬虫知識点(scrapy_redis分散爬虫システム)
30007 ワード
Scrapyとscrapy-redisの違い
Scrapyは一般的な爬虫類フレームワークであるが、分散はサポートされていない.Scrapy-redisは、Scrapy分散爬虫類をより容易に実現するために、redisベースのコンポーネント(コンポーネントのみ)をいくつか提供している.
pip install scrapy-redis
Scrapy-redisでは、次の4つのコンポーネント(components)が用意されています.(4つのコンポーネントは、この4つのモジュールが適切に変更されることを意味します)
scrapy-redisアーキテクチャ
上記の図に示すように、scrapy-redisはscrapyのアーキテクチャにredisを追加し、redisの特性に基づいて次のコンポーネントを拡張します.
Scrapyはpythonの本来のcollectionを改造した.Deque(双方向キュー)は独自のScrapy queue(https://github.com/scrapy/queuelib/blob/master/queuelib/queue.pyただし、Scrapyは複数のspiderで共有できません.つまり、Scrapy自体が爬虫分布式をサポートしていません.scrapy-redisの解決は、このScrapy queueをredisデータベース(redisキュー)に変換し、同じredis-serverから爬虫するrequestを格納することで、複数のspiderを同じデータベースに読み込ませることができます.
Scrapyにおいて「待ち行列」に直接関係するものは、スケジューラ
次にrequestの優先度に基づいて、どのキューに入れるかを決定し、列を出るときは優先度の小さい優先列で優先します.この比較的高度なキュー辞書を管理するために、Schedulerは一連の方法を提供する必要がある.しかし従来のSchedulerでは使用できなくなっているので、Scrapy-redisのschedulerコンポーネントを使用します.
Scrapyではこのrequestデリファクタ機能を集合で実現し,Scrapyでは既に送信されたrequest指紋を1つの集合に入れ,次のrequestの指紋を集合に持って行って照合し,その指紋が集合に存在する場合は,このrequestが送信されたことを説明し,なければ操作を継続する.このコアの重量判定機能はこのように実現されています.
scrapy−redisでの重量除去は
エンジン要求request(Spider発行)の場合、スケジューラはredisのrequest queueキュー⾥から優先度popに従って1つのrequestをエンジンに返し、エンジンはこのrequestをspider処理に送信する.
エンジンは(Spiderが返した)登ったItemをItem Pipelineに、scrapy-redisのItem Pipelineは登ったItemをredisのitems queueに格納します.
scrapyの既存のSpiderクラスは使用されず、書き換えられた
Spider継承RedisSpiderを生成するとsetup_が呼び出されますredis関数です.この関数はredisデータベースに接続され、signals(信号)が設定されます. spiderが空いているときのsignalはspiderを呼び出します.idle関数、この関数は itemを捕まえたときのsignalでitem_が呼び出されますscraped関数です.この関数は
Redisが実現する3つの機能:1:urlの指紋集合を要求する;
2:responseのリクエストキュー
3:一時的なitemデータ
ゼロからRedis-scrapy分布式爬虫類を構築する
Scrapy-Redis分散ポリシー:
Windows 10、Mac OS X、Ubuntu 16.04、CentOS 7.2の4つのコンピュータがあるとします.いずれのコンピュータもMaster側またはSlaver側として使用できます.たとえば、次のようになります. だけを担当します. に提出するまずSlaver側がMaster側からタスク(Request,url)を持ってデータをキャプチャし、Slaverがデータをキャプチャすると同時に、新しいタスクを生成したRequestがMaster処理にコミットされる. Master側には1つのRedisデータベースしかありません.未処理のRequestのデマンドとタスクの割り当てを担当し、処理後のRequestを待ち行列に追加し、取得したデータを格納します.
Scrapy-Redisのデフォルトでは、タスクスケジューリングなどの作業がすでに完了しているため、RedisSpiderを継承し、redis_を指定するだけで、このポリシーが使用されています.keyでいいです.
欠点は、Scrapy-RedisスケジューリングのタスクはRequestオブジェクトであり、情報量が比較的大きい(urlだけでなくcallback関数、headersなどの情報も含まれている)ため、結果として爬虫速度が低下し、Redisの大量の記憶領域が占有される可能性があるため、効率を保証するには一定のハードウェアレベルが必要になる.
一、Redisのインストール
Redisのインストール:http://redis.io/download
インストールが完了すると、Redisインストールディレクトリの下にあるredisをコピーします.confは任意のディレクトリに、
二、構成ファイルredisを修正する.conf
君のredisを開けろconfプロファイル、例:非Windowsシステム: Windowsシステム: Master端子redis.confには
三、Slave端のリモート接続Master端をテストする
テスト中、Master側Windows 10のIPアドレスは: Master側は、指定されたプロファイルに従って 非Windowsシステム: Windowsシステム:
Master側ローカル を起動 slave側は を表す.
注意:Slave端子は
四、Redisデータベースデスクトップ管理ツール
ここではRedis Desktop Managerをお勧めします.Windows、Mac OS X、Linuxなどのプラットフォームをサポートします.
ダウンロード先:https://redisdesktop.com/download
二、myspider_redis (class MySpider(RedisSpider))
この爬虫類はRedisSpiderを継承し,分布式のキャプチャをサポートし,basic spiderを採用し,parse関数を書く必要がある.
次にstart_がなくなりましたurlsが代わりにredis_key,scrapy-redisはkeyをRedisからpopし,要求されたurlアドレスとする.
注意:
RedisSpiderクラスは、 scrapy-redisは、構築方法 redis_を指定する必要がありますkey、すなわち爬虫類のコマンドを起動し、参照フォーマット: 指定されたフォーマットに従って、
実行方法: runspiderメソッドにより爬虫類のpyファイル(複数回に分けて実行することも可能)を実行し、爬虫類(達)は待機準備状態にある: Master側のredis-cliにpush命令を入力、参照フォーマット: Slaver端爬虫類は要求を取得し、爬虫類を開始する.
setting
Scrapyは一般的な爬虫類フレームワークであるが、分散はサポートされていない.Scrapy-redisは、Scrapy分散爬虫類をより容易に実現するために、redisベースのコンポーネント(コンポーネントのみ)をいくつか提供している.
pip install scrapy-redis
Scrapy-redisでは、次の4つのコンポーネント(components)が用意されています.(4つのコンポーネントは、この4つのモジュールが適切に変更されることを意味します)
Scheduler
Duplication Filter
Item Pipeline
Base Spider
scrapy-redisアーキテクチャ
上記の図に示すように、scrapy-redisはscrapyのアーキテクチャにredisを追加し、redisの特性に基づいて次のコンポーネントを拡張します.
Scheduler
: Scrapyはpythonの本来のcollectionを改造した.Deque(双方向キュー)は独自のScrapy queue(https://github.com/scrapy/queuelib/blob/master/queuelib/queue.pyただし、Scrapyは複数のspiderで共有できません.つまり、Scrapy自体が爬虫分布式をサポートしていません.scrapy-redisの解決は、このScrapy queueをredisデータベース(redisキュー)に変換し、同じredis-serverから爬虫するrequestを格納することで、複数のspiderを同じデータベースに読み込ませることができます.
Scrapyにおいて「待ち行列」に直接関係するものは、スケジューラ
Scheduler
であり、新たなrequestに対するエンキュー操作(Scrapy queueを加える)、次の登るrequest(Scrapy queueから取り出す)などの操作を担当する.待ち行列を優先順位に従って辞書構造を構築します.たとえば、次のようにします. {
0 : 0
1 : 1
2 : 2
}
次にrequestの優先度に基づいて、どのキューに入れるかを決定し、列を出るときは優先度の小さい優先列で優先します.この比較的高度なキュー辞書を管理するために、Schedulerは一連の方法を提供する必要がある.しかし従来のSchedulerでは使用できなくなっているので、Scrapy-redisのschedulerコンポーネントを使用します.
Duplication Filter
Scrapyではこのrequestデリファクタ機能を集合で実現し,Scrapyでは既に送信されたrequest指紋を1つの集合に入れ,次のrequestの指紋を集合に持って行って照合し,その指紋が集合に存在する場合は,このrequestが送信されたことを説明し,なければ操作を継続する.このコアの重量判定機能はこのように実現されています.
def request_seen(self, request):
# self.request_figerprints
fp = self.request_fingerprint(request)
#
if fp in self.fingerprints:
return True
self.fingerprints.add(fp)
if self.file:
self.file.write(fp + os.linesep)
scrapy−redisでの重量除去は
Duplication Filter
コンポーネントによって実現され,redisのsetの重複しない特性によってDuplication Filter重量除去が巧みに実現された.scrapy-redisスケジューラはエンジンからrequestを受け取り、requestの指紋をredisのsetに保存して重複するかどうかをチェックし、重複しないrequest pushをredisのrequest queueに書きます.エンジン要求request(Spider発行)の場合、スケジューラはredisのrequest queueキュー⾥から優先度popに従って1つのrequestをエンジンに返し、エンジンはこのrequestをspider処理に送信する.
Item Pipeline
: エンジンは(Spiderが返した)登ったItemをItem Pipelineに、scrapy-redisのItem Pipelineは登ったItemをredisのitems queueに格納します.
Item Pipeline
を修正すると、keyに基づいてitems queueからitemを抽出し、items processes
クラスタを実装するのに便利である.Base Spider
scrapyの既存のSpiderクラスは使用されず、書き換えられた
RedisSpider
はSpiderとRedisMixinの2つのクラスを継承し、RedisMixinはredisからurlを読み出すためのクラスである.Spider継承RedisSpiderを生成するとsetup_が呼び出されますredis関数です.この関数はredisデータベースに接続され、signals(信号)が設定されます.
schedule_next_request
関数を呼び出し、spiderが常に生きている状態であることを保証し、DontCloseSpider異常を放出する.schedule_next_request
関数を呼び出し、次のrequestを取得します.Redisが実現する3つの機能:1:urlの指紋集合を要求する;
2:responseのリクエストキュー
3:一時的なitemデータ
ゼロからRedis-scrapy分布式爬虫類を構築する
Scrapy-Redis分散ポリシー:
Windows 10、Mac OS X、Ubuntu 16.04、CentOS 7.2の4つのコンピュータがあるとします.いずれのコンピュータもMaster側またはSlaver側として使用できます.たとえば、次のようになります.
Master
(コアサーバ):Windows 10を使用して、Redisデータベースを構築し、登る責任を負いません.url指紋の重み、Requestの割り当て、およびデータの格納Slaver
(爬虫プログラム実行端):Mac OS X、Ubuntu 16.04、CentOS 7.2を使用して爬虫プログラムの実行を担当し、実行中に新しいRequestをMaster Scrapy-Redisのデフォルトでは、タスクスケジューリングなどの作業がすでに完了しているため、RedisSpiderを継承し、redis_を指定するだけで、このポリシーが使用されています.keyでいいです.
欠点は、Scrapy-RedisスケジューリングのタスクはRequestオブジェクトであり、情報量が比較的大きい(urlだけでなくcallback関数、headersなどの情報も含まれている)ため、結果として爬虫速度が低下し、Redisの大量の記憶領域が占有される可能性があるため、効率を保証するには一定のハードウェアレベルが必要になる.
一、Redisのインストール
Redisのインストール:http://redis.io/download
インストールが完了すると、Redisインストールディレクトリの下にあるredisをコピーします.confは任意のディレクトリに、
/etc/redis/redis.conf
に保存することをお勧めします(Windowsシステムは変更する必要はありません)二、構成ファイルredisを修正する.conf
君のredisを開けろconfプロファイル、例:
sudo vi /etc/redis/redis.conf
C:\Intel\Redis\conf\redis.conf
bind 127.0.0.1
と注記されており、Slave側はMaster側のRedisデータベースにリモート接続できます.daemonize yno
は、Redisがデフォルトでデーモンとして実行されていないことを示す.すなわち、redis-server /etc/redis/redis.conf
が実行されると、Redis起動プロンプト画面が表示される.daemonize yes
はデフォルトでバックグラウンドで実行され、新しいターミナルウィンドウを再起動して他のコマンドを実行する必要はありません.個人の好みと実際のニーズを見てください.三、Slave端のリモート接続Master端をテストする
テスト中、Master側Windows 10のIPアドレスは:
192.168.199.108
redis-server
を起動します.例:sudo redis-server /etc/redis/redis/conf
( )
モードでredis-server C:\Intel\Redis\conf\redis.conf
を実行してデフォルト構成を読み込むとよい.redis-cli
:redis-cli -h 192.168.199.108
を起動する、-hパラメータは指定ホストに接続されたredisデータベース注意:Slave端子は
redis-server
を起動する必要はなく、Master端子は起動すればよい.Slave側がMaster側のRedisデータベースに読み込まれていれば,接続が成功し,分散が可能であることを示す.四、Redisデータベースデスクトップ管理ツール
ここではRedis Desktop Managerをお勧めします.Windows、Mac OS X、Linuxなどのプラットフォームをサポートします.
ダウンロード先:https://redisdesktop.com/download
二、myspider_redis (class MySpider(RedisSpider))
この爬虫類はRedisSpiderを継承し,分布式のキャプチャをサポートし,basic spiderを採用し,parse関数を書く必要がある.
次にstart_がなくなりましたurlsが代わりにredis_key,scrapy-redisはkeyをRedisからpopし,要求されたurlアドレスとする.
from scrapy_redis.spiders import RedisSpider
class MySpider(RedisSpider):
"""Spider that reads urls from redis queue (myspider:start_urls)."""
name = 'myspider_redis'
# redis-key :
redis_key = 'myspider:start_urls'
# : allowd_domains(),__init__ , super()
def __init__(self, *args, **kwargs):
# Dynamically define the allowed domains list. #
domain = kwargs.pop('domain', '')
self.allowed_domains = filter(None, domain.split(','))
#
super(MySpider, self).__init__(*args, **kwargs)
def parse(self, response):
return {
'name': response.css('title::text').extract_first(),
'url': response.url,
}
注意:
RedisSpiderクラスは、
allowd_domains
とstart_urls
を書く必要はありません.__init__()
から爬虫類の爬虫領域範囲を動的に定義するか、allowd_domains
を直接書くかを選択することができる.redis_key = 'myspider:start_urls'
start_urls
はMaster側のredis-cliでlpushをRedisデータベースに、RedisSpiderはデータベースでstart_を取得するurls. 実行方法:
scrapy runspider myspider_redis.py
$redis > lpush myspider:start_urls http://www.dmoz.org/
setting
# -*- coding: utf-8 -*-
# Scrapy settings for youyuan project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
# http://doc.scrapy.org/en/latest/topics/settings.html
# http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html
# http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.html
BOT_NAME = 'youyuan'
SPIDER_MODULES = ['youyuan.spiders']
NEWSPIDER_MODULE = 'youyuan.spiders'
# scrapy-redis , scrapy
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# scrapy-redis , scrapy
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#
SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
# ,redis
SCHEDULER_PERSIST = True
# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'youyuan (+http://www.yourdomain.com)'
# Obey robots.txt rules
ROBOTSTXT_OBEY = True
# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32
# Configure a delay for requests for the same website (default: 0)
# See http://scrapy.readthedocs.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16
# Disable cookies (enabled by default)
#COOKIES_ENABLED = False
# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False
# Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# 'Accept-Language': 'en',
#}
# Enable or disable spider middlewares
# See http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
# 'youyuan.middlewares.MyCustomSpiderMiddleware': 543,
#}
# Enable or disable downloader middlewares
# See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
# 'youyuan.middlewares.MyCustomDownloaderMiddleware': 543,
#}
# Enable or disable extensions
# See http://scrapy.readthedocs.org/en/latest/topics/extensions.html
#EXTENSIONS = {
# 'scrapy.extensions.telnet.TelnetConsole': None,
#}
# Configure item pipelines
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'youyuan.pipelines.YouyuanPipeline': 300,
'scrapy_redis.pipelines.RedisPipeline' : 400,
}
# Enable and configure the AutoThrottle extension (disabled by default)
# See http://doc.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False
# Enable and configure HTTP caching (disabled by default)
# See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
redi item item
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
import MySQLdb
import json
def process_item():
# redis
rediscli = redis.Redis(host = "127.0.0.1", port = 6379, db = 0)
# mysql
mysqlcli = MySQLdb.connect(host = "127.0.0.1", port = 3306, \
user = "power", passwd = "60055969", db = "youyuan")
offset = 0
while True:
# redis pop
source, data = rediscli.blpop("yy:items")
item = json.loads(data)
try:
# mysql , mysql
cursor = mysqlcli.cursor()
cursor.execute("insert into beijing_18_25_mm (username, age, header_url, images_url, content, place_from, education, hobby, source_url, source, time, spidername) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", [item['username'], item['age'], item['header_url'], item['images_url'], item['content'], item['place_from'], item['education'], item['hobby'], item['source_url'], item['sourec'], item['time'], item['spidername']])
#
mysqlcli.commit()
#
cursor.close()
offset += 1
print offset
except:
pass
if __name__ == "__main__":
process_item()
redisデータをmongodbに転送import redis
import pymongo
import json
def process_item():
# redis
rediscli = redis.Redis(host = "127.0.0.1", port = 6379, db = "0")
# MongoDB
mongocli = pymongo.MongoClient(host = "127.0.0.1", port = 27017)
# mongodb
dbname = mongocli["youyuan"]
# mongodb youyuan
sheetname = dbname["beijing_18_25_mm"]
offset = 0
while True:
# redis
source, data = rediscli.blpop("yy:items")
offset += 1
# json Python
data = json.loads(data)
# sheetname
sheetname.insert(data)
print offset
if __name__ == "__main__":
process_item()