Как очистить сайты на основе AJAX с помощью Scrapy и Splash?

Я хочу сделать общий скребок, который может сканировать и очищать все данные с любого типа веб-сайта, включая веб-сайты AJAX. Я интенсивно искал в Интернете, но не смог найти какой-либо подходящей ссылки, которая могла бы объяснить мне, как Scrapy и Splash вместе могут очищать веб-сайты AJAX (которые включают в себя разбиение на страницы, данные формы и нажатие кнопки перед отображением страницы). Каждая ссылка, на которую я ссылался, говорит мне, что сайты Javascript могут отображаться с помощью Splash, но нет хорошего руководства / объяснения по использованию Splash для рендеринга сайтов JS. Пожалуйста, не предлагайте мне решения, связанные с использованием браузеров (я хочу делать все программно, приветствуются предложения безголовых браузеров... но я хочу использовать Splash).

class FlipSpider(CrawlSpider):
    name = "flip"
    allowed_domains = ["www.amazon.com"]

    start_urls = ['https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=mobile']  

    rules = (Rule(LinkExtractor(), callback='lol', follow=True),

    def parse_start_url(self,response):

       yield scrapy.Request(response.url, self.lol, meta={'splash':{'endpoint':'render.html','args':{'wait': 5,'iframes':1,}}})

    def lol(self, response):
       """
       Some code

3 ответа

Проблема с Splash и пагинацией заключается в следующем:

Мне не удалось создать сценарий Lua, который предоставляет новую веб-страницу (после нажатия на ссылку на страницу) в формате ответа. а не чистый HTML.

Итак, мое решение следующее - щелкнуть ссылку и извлечь этот новый сгенерированный URL и направить сканер на этот новый URL.

Итак, я на странице, которая имеет ссылку на страницы, я выполняю

yield SplashRequest(url=response.url, callback=self.get_url, endpoint="execute", args={'lua_source': script})

со следующим скриптом Lua

def parse_categories(self, response):
script = """
             function main(splash)
                 assert(splash:go(splash.args.url))
                 splash:wait(1)
                 splash:runjs('document.querySelectorAll(".next-page")[0].click()')
                 splash:wait(1)
                 return splash:url()  
             end
             """

и функция get_url

def get_url(self,response):
    yield SplashRequest(url=response.body_as_unicode(), callback=self.parse_categories)

Таким образом, я смог зациклить свои запросы.

Точно так же, если вы не ожидаете новый URL, ваш Lua-скрипт может просто создать чистый HTML, который вы должны использовать для регулярных выражений (это плохо), но это лучшее, что я смог сделать.

Вы можете эмулировать поведение, например, ckick или scroll, написав функцию JavaScript и сказав Splash, чтобы он выполнял этот скрипт при рендеринге вашей страницы.

Небольшой пример:

Вы определяете функцию JavaScript, которая выбирает элемент на странице и затем нажимает на него:

(источник: документ-заставка)

  -- Get button element dimensions with javascript and perform mouse click.
_script = """
function main(splash)
    assert(splash:go(splash.args.url))
    local get_dimensions = splash:jsfunc([[
        function () {
            var rect = document.getElementById('button').getClientRects()[0];
            return {"x": rect.left, "y": rect.top}
        }
    ]])
    splash:set_viewport_full()
    splash:wait(0.1)
    local dimensions = get_dimensions()
    splash:mouse_click(dimensions.x, dimensions.y)

    -- Wait split second to allow event to propagate.
    splash:wait(0.1)
    return splash:html()
end
"""

Потом, когда ты requestВы модифицируете endpoint и установите его "execute"и вы добавляете "lua_script": _script в args.

Пример:

def parse(self, response):
    yield SplashRequest(response.url, self.parse_elem,
                        endpoint="execute",
                        args={"lua_source": _script})

Вы найдете всю информацию о сценариях-заставках здесь

Я только что ответил на аналогичный вопрос здесь: очистка разбивки на страницы на основе ajax . Мое решение - получить текущую и последнюю страницы, а затем заменить переменную страницы в URL-адресе запроса.

Кроме того - еще одно, что вы можете сделать, это посмотреть на вкладку сети в инструментах разработчика браузера и посмотреть, можете ли вы идентифицировать какой-либо вызываемый API. Если вы посмотрите запросы в XHR, вы увидите те, которые возвращают json.

Затем вы можете напрямую вызвать API и проанализировать ответ json / html. Вот ссылка из документов scrapy: Сетевой инструмент

Другие вопросы по тегам