Как очистить сайты на основе 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: Сетевой инструмент