2017-01-13 14 views
2

Я учусь использовать всплеск. В качестве упражнения, я пытаюсь посетить https://www.ubereats.com/stores/, нажмите на текстовое поле адреса, введите местоположение и нажмите кнопку «Ввод», чтобы перейти к следующей странице, содержащей рестораны, доступные для этого места. У меня есть следующий код lua:Scrapy + splash: не может выбрать элемент

function main(splash) 
    local url = splash.args.url 
    assert(splash:go(url)) 
    assert(splash:wait(5)) 

    local element = splash:select('.base_29SQWm') 
    local bounds = element:bounds() 
    assert(element:mouseclick{x = bounds.width/2, y = bounds.height/2}) 
    assert(element:send_text("Wall Street")) 
    assert(splash:send_keys("<Return>")) 
    assert(splash:wait(5)) 

    return { 
    html = splash:html(), 
    } 
end 

Когда я нажимаю «Render!» в выплеске API, я получаю следующее сообщение об ошибке:

{ 
     "info": { 
      "message": "Lua error: [string \"function main(splash)\r...\"]:7: attempt to index local 'element' (a nil value)", 
      "type": "LUA_ERROR", 
      "error": "attempt to index local 'element' (a nil value)", 
      "source": "[string \"function main(splash)\r...\"]", 
      "line_number": 7 
     }, 
     "error": 400, 
     "type": "ScriptError", 
     "description": "Error happened while executing Lua script" 
    } 

Как-то мое выражение КССА лжи, в результате чего всплеска пытается получить доступ к элементу, который является неопределенным/нолем! Я пробовал другие выражения, но я не могу понять это!

Вопрос: Кто-нибудь знает, как решить эту проблему?

EDIT: Даже если я все еще хотел бы знать, как на самом деле нажмите на элемент, я понял, как получить тот же результат, используя только клавиши:

function main(splash) 
    local url = splash.args.url 
    assert(splash:go(url)) 
    assert(splash:wait(5)) 
    splash:send_keys("<Tab>") 
    splash:send_keys("<Tab>") 
    splash:send_text("Wall Street, New York") 
    splash:send_keys("<Return>") 
    assert(splash:wait(10)) 

    return { 
    html = splash:html(), 
    png = splash:png(), 
    } 
    end 

Однако, возвращаемые HTML/изображения в API всплеска со страницы, на которой вы вводите адрес, а не на странице, которую видите после того, как вы ввели свой адрес и нажали кнопку ввода.

Q2: Как я могу успешно загрузить вторую страницу?

ответ

4

не полное решение, но вот то, что я до сих пор:

import json 
import re 

import scrapy 
from scrapy_splash import SplashRequest 


class UberEatsSpider(scrapy.Spider): 
    name = "ubereatspider" 
    allowed_domains = ["ubereats.com"] 

    def start_requests(self): 
     script = """ 
     function main(splash) 
      local url = splash.args.url 
      assert(splash:go(url)) 
      assert(splash:wait(10)) 

      splash:set_viewport_full() 

      local search_input = splash:select('#address-selection-input') 
      search_input:send_text("Wall Street, New York") 
      assert(splash:wait(5)) 

      local submit_button = splash:select('button[class^=submitButton_]') 
      submit_button:click() 

      assert(splash:wait(10)) 

      return { 
       html = splash:html(), 
       png = splash:png(), 
      } 
      end 
     """ 
     headers = { 
      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36' 
     } 
     yield SplashRequest('https://www.ubereats.com/new_york/', self.parse, endpoint='execute', args={ 
      'lua_source': script, 
      'wait': 5 
     }, splash_headers=headers, headers=headers) 

    def parse(self, response): 
     script = response.xpath("//script[contains(., 'cityName')]/text()").extract_first() 
     pattern = re.compile(r"window.INITIAL_STATE = (\{.*?\});", re.MULTILINE | re.DOTALL) 

     match = pattern.search(script) 
     if match: 
      data = match.group(1) 
      data = json.loads(data) 
      for place in data["marketplace"]["marketplaceStores"]["data"]["entity"]: 
       print(place["title"]) 

Обратите внимание на изменения в скрипте Lua: Я обнаружил вход поиска, отправить текст для поиска к нему, то находится кнопку «Найти» и щелкнул по ней. На скриншоте я не видел, чтобы результаты поиска загружались независимо от времени задержки, которую я установил, но мне удалось получить названия ресторанов из содержимого script. Объекты place содержат всю необходимую информацию для фильтрации желаемых ресторанов.

Также обратите внимание, что URL, к которому я отношусь, является «Нью-Йорк» (не общий «магазин»).

Я не совсем уверен, почему страница с результатами поиска не загружается, но надеюсь, что это будет хорошим началом для вас, и вы сможете улучшить это решение.

+0

Спасибо за ваш ответ! Однако, когда я создаю ваш скрипт lua в API-интерфейсе splash, я получаю следующее сообщение: '" error ":« попытка индексировать локальный «search_input» (значение nil) », « line_number »: 9'. По-видимому, всплеск не распознает '# address-selection-input'. Как вы пришли к этим селекторам css? Я не могу найти их, когда я проверяю страницу; может ли это иметь какое-то отношение к моему местоположению? – titusAdam

+0

Это случай, когда количество javascript является такой проблемой, что мы хотим использовать селен? (так как в этом скрипте нужно ждать 25 секунд) – titusAdam

+0

@titusAdam Я подозреваю, что так, но пока не могу доказать это. С селеном вещи должны идти проще, если вы в порядке с обработкой его селеном - я могу предоставить рабочий образец. Что касается селекторов, используемых в коде - я проверил код HTML на странице и получил селектор - работает для меня из двух разных мест. Благодарю. – alecxe