2016-04-04 10 views
5

Sto usando ScrapyJS e Splash per simulare una forma pulsante di invio clicScrapyJS - Come attendere correttamente il caricamento della pagina?

def start_requests(self): 
     script = """ 
     function main(splash) 
      assert(splash:autoload("https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js")) 
      assert(splash:go(splash.args.url)) 

      local js = [[ 
       var $j = jQuery.noConflict(); 
       $j('#USER').val('frankcastle'); 
       $j('#password').val('punisher'); 
       $j('.button-oblong-orange.button-orange a').click(); 
      ]] 

      assert(splash:runjs(js)) 

      local resumeJs = [[ 
       function main(splash) { 
        var $j = jQuery.noConflict(); 
        $j(document).ready(function(){ 
         splash.resume(); 
        }) 
       } 
      ]] 

     assert(splash:wait_for_resume(resumeJs)) 

      return { 
       html = splash:html() 
      } 
     end 
     """ 
     splash_meta = {'splash': {'endpoint': 'execute', 'args': {'wait': 0.5, 'lua_source': script}}} 

     for url in self.start_urls: 
      yield scrapy.Request(url, self.after_login, meta=splash_meta) 

def after_login(self, response): 
     print response.body 
     return 

Dopo aver fatto splash:runjs(js), sto ricorrere a splash:wait(5) cercato splash:wait_for_resume per ottenere il risultato. Questo potrebbe non funzionare sempre (latenza di rete), quindi c'è un modo migliore?

+1

Abbastanza sicuro schizzi consente di attendere un elemento sia visibile –

+0

@PadraicCunningham Si prega di controllare la mia modifica, schizzi provato: wait_for_resume (non so se sto facendo in modo corretto), ma senza fortuna – Krishnaraj

+0

trovato un problema simile - https://github.com/scrapinghub/splash/issues/200 – Krishnaraj

risposta

4

Si scopre che l'unico modo è utilizzare splash:wait() ma farlo in un ciclo e verificare la disponibilità di alcuni elementi (come il piè di pagina).

def start_requests(self): 
     script = """ 
     function main(splash) 
      assert(splash:autoload("https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js")) 
      assert(splash:go(splash.args.url)) 

      local js = [[ 
       var $j = jQuery.noConflict(); 
       $j('#USER').val('frankcastle'); 
       $j('#password').val('punisher'); 
       $j('.button-oblong-orange.button-orange a').click(); 
       $j('body').empty() // clear body, otherwise the wait_for footer will always be true 
      ]] 

      assert(splash:runjs(js)) 

      function wait_for(splash, condition) 
       while not condition() do 
        splash:wait(0.05) 
       end 
      end 

      wait_for(splash, function() 
       return splash:evaljs("document.querySelector('#footer') != null") 
      end) 

      return { 
       html = splash:html() 
      } 
     end 
     """ 
     splash_meta = {'splash': {'endpoint': 'execute', 'args': {'wait': 0.5, 'lua_source': script}}} 

     for url in self.start_urls: 
      yield scrapy.Request(url, self.after_login, meta=splash_meta) 
0

Quindi non ho ancora giocato con questo (ho ottenuto Lua e alcuni tentativi riusciti con Splash solo oggi).

se si fa qualcosa di simile:

recheck = True 

html = splash:html() 
splash:wait(0.5) 
while recheck = True: 
    splash:wait(0.5) 
    html2 = splash:html() 
    if html != html2: 
     pass 
    elif: 
     recheck = False 
     return { 
      html = splash:html(), 
     } 

Gonna essere usando la cosa simile per le pagine di scorrimento infinito che popolano voci di elenco in risposta a rotoli (o Page_downs)

Siamo spiacenti per scarsa familiarità con la Lua/Splash syntax

0

C'è un modo un po 'migliore per controllarlo, ma nonostante ciò è necessario un ciclo con le attese. L'idea è di usare splash:on_response(response) come richiamata quando la pagina viene aggiornata. Si noti che la richiamata della risposta sarà chiamata asincrona, quindi il ciclo principale deve attendere tutte le modifiche della pagina, ecco perché abbiamo un ciclo di 'attesa' (ad esempio dato da @Krishnaraj).

Di seguito viene fornito un esempio con il pulsante button_id per 10 volte, per il download di contenuto aggiuntivo.

function main(splash) 
    assert(splash:go(splash.args.url)) 

    function wait_for(splash, condition) 
     while not condition() do 
      splash:wait(0.2) 
     end 
    end 

    local clicks = 0 

    splash:on_response(function(res) 
     clicks = clicks + 1 

     if clicks < 10 then 
      assert(splash:runjs("document.getElementById(\"button_id\").click();")) 
     end 
    end) 

    assert(splash:runjs("document.getElementById(\"button_id\").click();")) 

    wait_for(splash, function() 
     return clicks >= 10 
    end) 

    return splash:html() 
end 
Problemi correlati