Загрузка веб-страницы SPA через AJAX
Я пытаюсь получить всю веб-страницу с помощью JavaScript, подключив URL-адрес. Однако веб-сайт построен как одностраничное приложение (SPA), которое использует JavaScript / костяк.js динамически загружать большую часть его содержимого после отрисовки начального ответа.
так, например, когда я маршрут по следующему адресу:
https://connect.garmin.com/modern/activity/1915361012
а затем введите это в консоль (после загрузки страницы):
var $page = $("html")
console.log("%c✔: ", "color:green;", $page.find(".inline-edit-target.page-title-overflow").text().trim());
console.log("%c✔: ", "color:green;", $page.find("footer .details").text().trim());
тогда я получу динамически загружаемый заголовок действия, а также статически загруженный нижний колонтитул страницы:
, когда я пытаюсь загрузить веб-страницу с помощью вызова AJAX с помощью $.get()
или .load()
, Я получаю только первоначальный ответ (такой же, как контент, когда над view-source):
view-source:https://connect.garmin.com/modern/activity/1915361012
поэтому, если я использую один из следующих вызовов AJAX:
// jQuery.get()
var url = "https://connect.garmin.com/modern/activity/1915361012";
jQuery.get(url,function(data) {
var $page = $("<div>").html(data)
console.log("%c✖: ", "color:red;", $page.find(".page-title").text().trim());
console.log("%c✔: ", "color:green;", $page.find("footer .details").text().trim());
});
// jQuery.load()
var url = "https://connect.garmin.com/modern/activity/1915361012";
var $page = $("<div>")
$page.load(url, function(data) {
console.log("%c✖: ", "color:red;", $page.find(".page-title").text().trim() );
console.log("%c✔: ", "color:green;", $page.find("footer .details").text().trim());
});
Я все равно получу начальный нижний колонтитул, но не получит никакого другого содержимого страницы:
Я пробовал решение здесь to eval()
содержание каждого script
тег, но это не кажется достаточно прочным, чтобы загрузить страницу:
jQuery.get(url,function(data) {
var $page = $("<div>").html(data)
$page.find("script").each(function() {
var scriptContent = $(this).html(); //Grab the content of this tag
eval(scriptContent); //Execute the content
});
console.log("%c✖: ", "color:red;", $page.find(".page-title").text().trim());
console.log("%c✔: ", "color:green;", $page.find("footer .details").text().trim());
});
Q: какие-либо параметры для полной загрузки веб-страницы, которая будет соскабливаться через JavaScript?
3 ответов
вы никогда не сможете полностью воспроизвести самостоятельно, что делает произвольная (SPA) страница.
единственный способ, который я вижу, - это использовать безголовый браузер, такой как PhantomJS или Безголовый Хром или Безголовый Firefox.
Я хотел попробовать Headless Chrome, поэтому давайте посмотрим, что он может сделать с вашей страницей:
быстрая проверка с помощью внутреннего REPL
загрузите эту страницу с Chrome безголовым (вам понадобится Chrome 59 на Mac / Linux, Chrome 60 в Windows) и найдите заголовок страницы с JavaScript из REPL:
% chrome --headless --disable-gpu --repl https://connect.garmin.com/modern/activity/1915361012
[0830/171405.025582:INFO:headless_shell.cc(303)] Type a Javascript expression to evaluate or "quit" to exit.
>>> $('body').find('.page-title').text().trim()
{"result":{"type":"string","value":"Daily Mile - Round 2 - Day 27"}}
NB: чтобы получить chrome
командная строка, работающая на Mac, я сделал это заранее:
alias chrome="'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'"
использование программно с Node & Puppeteer
Кукловод - это библиотека узлов (разработчиками Google Chrome), которая предоставляет API высокого уровня для управления безголовым Chrome по протоколу DevTools. Его можно также установить для использования полного (безголовый) хром.
(Шаг 0 : Установка узел & пряжа если у вас их нет)
в новом каталоге:
yarn init
yarn add puppeteer
создать index.js
С этого:
const puppeteer = require('puppeteer');
(async() => {
const url = 'https://connect.garmin.com/modern/activity/1915361012';
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Go to URL and wait for page to load
await page.goto(url, {waitUntil: 'networkidle'});
// Wait for the results to show up
await page.waitForSelector('.page-title');
// Extract the results from the page
const text = await page.evaluate(() => {
const title = document.querySelector('.page-title');
return title.innerText.trim();
});
console.log(`Found: ${text}`);
browser.close();
})();
результат:
$ node index.js
Found: Daily Mile - Round 2 - Day 27
во-первых: избежать eval
- ваша политика безопасности контента должна блокировать ее, и она оставляет вас открытыми для простых атак XSS. Scraping bots определенно не будет запускать его.
проблема, которую вы описываете, является общей для всех спа - салонов-когда человек посещает, они получают сценарий оболочки приложения, который затем загружается в остальную часть контента - все хорошо. Когда бот посещает, они игнорируют скрипты и возвращают пустую оболочку.
решение является сервер обработки. Один из способов сделать это, если вы используете JS-рендерер (скажем, React) и узел.js на сервере вы можете довольно легко построить JS и обслуживать его статически.
однако, если вы этого не сделаете, вам нужно будет запустить безголовый браузер на вашем сервере, который выполняет все JS, которые пользователь будет, а затем подает результат боту.
к счастью кто-то уже сделал всю работу здесь. Они поставили демо онлайн, что вы можете попробуйте с вашим сайт:
Я думаю, вы должны знать концепцию SPA,
SPA-это одностраничное приложение, это только статический html-файл. когда маршрут изменится, страница создаст или изменит DOM
узлы динамически для достижения эффекта страницы переключения с помощью Javascript.
поэтому, если вы используете $.get()
, сервер ответит на статический html-файл со стабильной страницей, поэтому вы не будете загружать то, что хотите.
если вы хотите использовать $.get()
, Он имеет два способа, первый из которых использует headless browser
, например, headless chrome
, phantomJS
и т. д. Это поможет вам загрузить страницу и вы можете сделать dom
узлы загруженной страницы.Второй -SSR
(Server Slide Render
), если вы используете SSR
, вы получите HTML-данные страницы непосредственно $.get
, потому что данные HTML ответа сервера соответствуют странице при запросе различных маршрутов.
ссылки:
рамка SRR vue: Nuxt.js