Scripyフレームの使用のScrpyドッキングSplash

10081 ワード

前のセクションでは、ScrpyドッキングSeleniumがタオバオ商品を取り込む過程を実現しました.これはJavaScriptのダイナミックなページをキャプチャする方式です.Selenium以外にもSplashは同じ機能を実現します.今回はScrpyドッキングSplashによるページキャプチャの方法を理解します.
一、準備工作
Splashが正しくインストールされて正常に動作していることを確認してください.Slapy-splashライブラリをインストールします.
二、新規プロジェクト
まず新しいプロジェクトを作成します.scrapysplshtestといいます.コマンドは以下の通りです.
scrapy startproject scrapysplashtest
新しいSpiderを作成します.コマンドは以下の通りです.
scrapy genspider taobao www.taobao.com
三、設定を追加する
Scrpy-splashの構成説明を参考にして、一歩ずつの構成ができます.リンクは以下の通りです.https://github.com/scrapy-plugins/scrapy-splash#configuration.
settings.pyを変更し、SPLASH_URLを構成する.ここで私達のSplashは当地で運行していますので、直接地元の住所を設定できます.
SPLASH_URL = 'http://localhost:8050'
Splashがリモートサーバで実行されている場合、ここはリモートのアドレスに設定されるべきです.例えば、IPが120.27.34.25のサーバ上で実行される場合、ここでは以下のように構成されるべきである.
SPLASH_URL = 'http://120.27.34.25:8050'
いくつかのMiddlewareを配置する必要があります.コードは以下の通りです.
DOWNLOADER_MIDDLEWARES = {
    'scrapy_splash.SplashCookiesMiddleware': 723,
    'scrapy_splash.SplashMiddleware': 725,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
SPIDER_MIDDLEWARES = {
    'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
ここには三つのDownloader Middlewareと一つのSpider Middlewareが配置されています.これはScripy-splashの中心部分です.私達はもうドッキングSeleniumのようにDownloader Middlewareを実現する必要がありません.Scripy-splashライブラリは全部私達のために準備しました.直接配置すればいいです.
また、DUPEFILTER_CLASSの重いクラスを構成する必要があります.コードは以下の通りです.
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
最後に1つのCacheを構成してHTTPCACHE_STORAGEを記憶し、コードは以下の通りである.
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
四、新規要求
設定が完了したら、Splashを利用してページをつかむことができます.SplashRequestオブジェクトを直接生成して、対応するパラメータを渡すことができます.Scrpyはこの要求をSplashに転送し、Splashはページをレンダリングしてロードし、レンダリング結果を戻します.この時のResonseの内容はレンダリングが完了したページの結果です.最後にSpiderに解析してください.
次のような例を示します.
yield SplashRequest(url, self.parse_result,
    args={
        # optional; parameters passed to Splash HTTP API
        'wait': 0.5,
        # 'url' is prefilled from request url
        # 'http_method' is set to 'POST' for POST requests
        # 'body' is set to request body for POST requests
    },
    endpoint='render.json', # optional; default is render.html
    splash_url='',     # optional; overrides SPLASH_URL
)
ここでは、SplashRequestオブジェクトが構築されており、最初の2つのパラメータは依然として要求されたURLとコールバック関数である.また、argsを介して、待ち時間waitなどのレンダリングパラメータを伝えることもでき、endpointパラメータに従ってレンダリングインターフェースを指定することもできます.詳細なパラメータは文書の説明を参照できます.https://github.com/scrapy-plugins/scrapy-splash#requests.
また、Requestオブジェクトを生成することもできます.Splashの構成はmeta属性構成で結構です.コードは以下の通りです.
yield scrapy.Request(url, self.parse_result, meta={
    'splash': {
        'args': {
            # set rendering arguments here
            'html': 1,
            'png': 1,
            # 'url' is prefilled from request url
            # 'http_method' is set to 'POST' for POST requests
            # 'body' is set to request body for POST requests
        },
        # optional parameters
        'endpoint': 'render.json',  # optional; default is render.json
        'splash_url': '',      # optional; overrides SPLASH_URL
        'slot_policy': scrapy_splash.SlotPolicy.PER_DOMAIN,
        'splash_headers': {},       # optional; a dict with headers sent to Splash
        'dont_process_response': True, # optional, default is False
        'dont_send_headers': True,  # optional, default is False
        'magic_response': False,    # optional, default is True
    }
})
SplashRequestオブジェクトはargsによって構成され、かつRequestオブジェクトはmetaによって構成され、両方の方法で達成される効果は同じである.
今回のスナップショットは淘宝商品の情報です.ページのロード待ち、ページのめくりなどの操作に関連しています.まずLuaスクリプトを定義して、ページのロード、アナログクリックでページをめくる機能を実現できます.コードは下記の通りです.
function main(splash, args)
  args = {
    url="https://s.taobao.com/search?q=iPad",
    wait=5,
    page=5
  }
  splash.images_enabled = false
  assert(splash:go(args.url))
  assert(splash:wait(args.wait))
  js = string.format("document.querySelector('#mainsrp-pager div.form > input').value=%d;document.querySelector('#mainsrp-pager div.form > span.btn.J_Submit').click()", args.page)
  splash:evaljs(js)
  assert(splash:wait(args.wait))
  return splash:png()
end
要求されたリンクurl、待ち時間wait、改ページページページ番号pageの3つのパラメータを定義した.その後、画像のロードを無効にし、タオバオの商品リストページを要求し、evaljs()方法でJavaScriptコードを呼び出し、ページ番号の充填とページクリックを実現し、最後にスクリーンショットに戻る.スクリプトをSplashに置いて実行します.正常にページのスクリーンショットを取得しました.下の図のように.
ページをめくる作業も成功しました.下の図のように現在のページ番号です.私達が入ってきたページ番号pageのパラメータと同じです.
私たちはSpiderの中でLuaスクリプトをSplashRequestでドッキングするだけでいいです.次のようにします.
from scrapy import Spider
from urllib.parse import quote
from scrapysplashtest.items import ProductItem
from scrapy_splash import SplashRequest

script = """
function main(splash, args)
  splash.images_enabled = false
  assert(splash:go(args.url))
  assert(splash:wait(args.wait))
  js = string.format("document.querySelector('#mainsrp-pager div.form > input').value=%d;document.querySelector('#mainsrp-pager div.form > span.btn.J_Submit').click()", args.page)
  splash:evaljs(js)
  assert(splash:wait(args.wait))
  return splash:html()
end
"""

class TaobaoSpider(Spider):
    name = 'taobao'
    allowed_domains = ['www.taobao.com']
    base_url = 'https://s.taobao.com/search?q='

    def start_requests(self):
        for keyword in self.settings.get('KEYWORDS'):
            for page in range(1, self.settings.get('MAX_PAGE') + 1):
                url = self.base_url + quote(keyword)
                yield SplashRequest(url, callback=self.parse, endpoint='execute', args={'lua_source': script, 'page': page, 'wait': 7})
Luaスクリプトを成長文字列として定義し、SplashRequestargsを介してパラメータを伝達し、インタフェースをexecuteに修正した.また、argsパラメータには、Luaスクリプトの内容を指定するためのlua_sourceフィールドがあります.これにより、SplashRequestを構成することに成功し、Splashとのドッキングが完了しました.
他の構成は変更する必要はありません.Item、Item Pipelineなどの設定は前のセッションSeleniumと同じです.parse()コールバック関数も完全に一致しています.
五、運行
次に、以下の命令で爬虫類を実行します.
scrapy crawl taobao
運転結果は下図のようになります.
SplashとScripyは非同期処理をサポートしていますので、同時に複数のキャプチャ成功の結果が見られます.Seleniumのドッキング中に、各ページのレンダリングダウンロードはDownloader Middlewareで行われますので、全体のプロセスはブロックされています.Scripyは、このプロセスが完了するのを待って他の要求を処理し、スケジュールすることができます.これは登山の効率に影響します.そのためSplashを使って登るのはSeleniumより効率が高いです.
最後にもう一度MongoDBの結果を見ます.下の図のように.
結果は同様にMongoDBに正常に保存されています.
六、本節コード
このセクションのコードアドレスは:https://github.com/Python3WebSpider/ScrapySplashTest.
おわりに
したがって、Scripyでは、JavaScript動的にレンダリングされたページをSplashで処理することが推奨されている.このようにScripyにおける非同期処理の過程を破壊することなく、登用効率を大幅に向上させます.またSplashの設置と配置は比較的簡単であり、API呼び出しによりモジュール分離が実現され、大規模なウォーキングの配置もより便利である.