2016-06-26 14 views
4

私はGoogle Scholar search resultsをクロールしようとしており、検索結果に一致する各結果のすべてのBiBTeX形式を取得しようとしています。今私はスプラッシュを持つScrapyクローラーを持っています。私は、引用のBibTeX形式のhrefを得る前に、 "引用"リンクをクリックしてモーダルウィンドウをロードするluaスクリプトを持っています。しかし、複数の検索結果があり、複数の「引用」リンクがあることを確認するには、それらをすべてクリックして個々のBibTeXページをロードする必要があります。ここで スプラッシュluaスクリプトを複数回クリックして訪問する

は、私が持っているものです。

import scrapy 
from scrapy_splash import SplashRequest 


class CiteSpider(scrapy.Spider): 
    name = "cite" 
    allowed_domains = ["scholar.google.com", "scholar.google.ae"] 
    start_urls = [ 
     'https://scholar.google.ae/scholar?q="thermodynamics"&hl=en' 
    ] 

    script = """ 
     function main(splash) 
      local url = splash.args.url 
      assert(splash:go(url)) 
      assert(splash:wait(0.5)) 
      splash:runjs('document.querySelectorAll("a.gs_nph[aria-controls=gs_cit]")[0].click()') 
      splash:wait(3) 
      local href = splash:evaljs('document.querySelectorAll(".gs_citi")[0].href') 
      assert(splash:go(href)) 
      return { 
      html = splash:html(), 
      png = splash:png(), 
      href=href, 
      } 
     end 
     """ 

    def parse(self, response): 
     yield SplashRequest(self.start_urls[0], self.parse_bib, 
          endpoint="execute", 
          args={"lua_source": self.script}) 

    def parse_bib(self, response): 
     filename = response.url.split("/")[-2] + '.html' 
     with open(filename, 'wb') as f: 
      f.write(response.css("body > pre::text").extract()[0]) 

私はquerySelectorAll呼び出しを実行するとき、私はLuaのスクリプトに「シテ」リンクのインデックスを渡す必要があると思っていますが、私は見つけることができないよう他の変数を関数に渡すことができます。また、私はBibTeXを取得した後に元の結果ページに戻るためにいくつかの汚いjavascript history.back()を行う必要があると仮定しますが、私はこれを扱うよりエレガントな方法があると感じています。

答えて

0

わかりましたので、私はうまく機能するソリューションをハッキングしました。

def script(n): 
    _script = """ 
     function main(splash) 
      local url = splash.args.url 
      local href = "" 
      assert(splash:go(url)) 
      assert(splash:wait(0.5)) 
      splash:runjs('document.querySelectorAll("a.gs_nph[aria-controls=gs_cit]")[{}].click()') 
      splash:wait(3) 
      href = splash:evaljs('document.querySelectorAll("a.gs_citi")[0].href') 
      assert(splash:go(href)) 
      return {} 
     end 
     """.format(n, "{html=splash:html(),png=splash:png(), href=href,}") 
    return _script 

それはページ上のすべての「シテ」のリンクをクリックするように、私はその後、parse機能を変更する必要がありました:まず第一に、私たちは変更可能であることをLuaのスクリプトが必要になりますので、我々はそれを機能させますよ。それを行う方法は、ページ上のすべての一致する「引用」リンクを繰り返して、それぞれを個別にクリックすることです。私はLuaスクリプトにページを再度ロードさせました(これは汚いですが、他の方法は考えられません)、照会された "引用"リンクのインデックスをクリックします。このことができます

def parse(self, response): 
     n = len(response.css("a.gs_nph[aria-controls=gs_cit]").extract()) 
     for i in range(n): 
      yield SplashRequest(response.url, self.parse_bib, 
           endpoint="execute", 
           args={"lua_source": script(i)}, 
           dont_filter=True) 

希望:また、それはdont_filter=Trueがある理由は、したがって、重複するリクエストを作成する必要があります。

+3

FYI: 'SplashRequest(...、args = {" lua_source ":スクリプト、" n ":n})'に 'n '引数を渡してスクリプトから' splash.args n。この方法では、文字列の書式設定は必要ありません。文字列の書式設定にはいくつかの欠点があります。コードの数が増え、有効なLua(整数変数ではn/a)にエスケープする必要があり、キャッシングでうまくいきません(スプラッシュでスクリプトをキャッシュできるため、リクエストごとにスクリプトを送信する)。 –

関連する問題