Не могу удалить все данные cheerio - node.js - PullRequest
0 голосов
/ 10 октября 2019

js noob здесь,

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

Я тестирую этот конкретный URL:

https://www.trivago.fr/?aDateRange%5Barr%5D=2019-10-09&aDateRange%5Bdep%5D=2019-10-10&aPriceRange%5Bfrom%5D=0&aPriceRange%5Bto%5D=0&iRoomType=7&aRooms%5B0%5D%5Badults%5D=2&cpt2=22748%2F200&iViewType=0&bIsSeoPage=0&sortingId=1&slideoutsPageItemId=&iGeoDistanceLimit=20000&address=&addressGeoCode=&offset=0&ra=

Это то, что я получаю 1 из 20 попыток:

{ prices:
   [ 'Prix / nuit',
     'Hébergement',
     'Avis',
     'Emplacement',
     'Autres',
     'max. 500€+',
     'Bien',
     '108€',
     'Bien',
     '112€',
     'Excellent',
     '98€',
     'Très bien',
     '122€',
     'Très bien',
     '164€',
     'Excellent',
     '156€',
     'Très bien',
     '97€',
     'Très bien',
     '160€',
     'Très bien',
     '155€',
     ' ',
     '87€',
     'Excellent',
     '134€',
     'Très bien',
     '155€',
     ' ',
     '92€',
     'Excellent',
     '135€',
     'Très bien',
     '135€',
     'Excellent',
     '94€',
     ' ',
     '82€',
     'Très bien',
     '98€',
     'Excellent',
     '99€',
     'Bien',
     '110€',
     'Bien',
     '141€',
     ' ',
     '80€',
     'Très bien',
     '136€',
     'Excellent',
     '122€',
     'Excellent',
     '232€',
     '1',
     'trivago N.V.' ] }

и это то, что яполучить большую часть времени:

{ prices:
   [ 'Prix / nuit',
     'Hébergement',
     'Avis',
     'Emplacement',
     'Autres',
     'max. 500€+',
     'trivago N.V.' ] }

Мне сказали, что это может иметь какое-то отношение к скорости, с которой данные собираются, код завершится до того, как все данные будут получены

код:

const puppeteer = require('puppeteer');
let cheerio = require('cheerio');
let jsonframe = require('jsonframe-cheerio');

const server = http.createServer((req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World\n');
});

server.listen(port);

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    let frame;

    await page.goto('https://www.trivago.fr/?aDateRange%5Barr%5D=2019-10-09&aDateRange%5Bdep%5D=2019-10-10&aPriceRange%5Bfrom%5D=0&aPriceRange%5Bto%5D=0&iRoomType=7&aRooms%5B0%5D%5Badults%5D=2&cpt2=22748%2F200&iViewType=0&bIsSeoPage=0&sortingId=1&slideoutsPageItemId=&iGeoDistanceLimit=20000&address=&addressGeoCode=&offset=0&ra=');
    let bodyHTML = await page.evaluate(() => document.body.innerHTML).then(frame = {"prices": ["strong"]});
    let $ = cheerio.load(bodyHTML);
    jsonframe($);
    var postsList = $('body').scrape(frame);
    console.log(postsList);
    await browser.close();
})();

1 Ответ

0 голосов
/ 27 октября 2019
  1. Сайт, который вы анализируете, Trivago, используйте AJAX со следующими запросами: https://cdn-hs-graphql-dus.trivago.com/graphql. Вы можете проанализировать ответ, используя анализатор JSON, поэтому вам следует узнать об этом, если вы не хотите анализировать с Puppeteer.
  2. Если вы не хотите шпионить за этим запросом (используя chrome devtools), я предлагаю вамиспользовать кукловод. В кукловоде вы можете использовать метод waitForSelector. Например, если вы хотите получить название и цену некоторых отелей, вы можете подождать, пока селектор будет доступен в DOM, или просто подождать несколько секунд.
  3. Если вы хотите извлечь некоторые данные с помощью jsonframe, выТакже следует узнать больше о CSS-селекторе. Я предпочитаю использовать атрибуты [itemtype=""] и [itemprop=""], так как этот селектор надежен и его быстро найти.
    https://css -tricks.com / how-css-selectors-work /
  4. Для отображения данных вы можете использовать console.log, но если вы предпочитаете использовать узел.js в качестве сервера, я предлагаю вам использовать экспресс.
  5. Чтобы ваш скрипт работал быстро, вы можете заблокировать изображения из запроса, используя перехватчик.
  6. В приведенном выше коде выотсутствует связь между cheerio и jsonframe jsonframe($)
  7. Вы можете использовать эти коды в качестве примера.
(async () => {

    const http = require('http');
    const puppeteer = require('puppeteer');
    const cheerio = require('cheerio');
    const jsonframe = require('jsonframe-cheerio');

    const browser = await puppeteer.launch();
    const page = await browser.newPage();

    page.setDefaultNavigationTimeout(0);
    page.setRequestInterception(true);

    page.on('request', async request => {
        if ( request.resourceType() === 'image' || request.resourceType() === 'media' ) {
            request.abort();
        } else {
            request.continue();
        }
    });

    const response = await page.goto('https://www.trivago.fr/?aDateRange%5Barr%5D=2019-10-09&aDateRange%5Bdep%5D=2019-10-10&aPriceRange%5Bfrom%5D=0&aPriceRange%5Bto%5D=0&iRoomType=7&aRooms%5B0%5D%5Badults%5D=2&cpt2=22748%2F200&iViewType=0&bIsSeoPage=0&sortingId=1&slideoutsPageItemId=&iGeoDistanceLimit=20000&address=&addressGeoCode=&offset=0&ra=');
    const waitForAJAXComplete = await page.waitForSelector('h3[itemprop="name"]>span.item-link');
    const bodyHTML = await page.content();
    const exit = await browser.close();

    const $ = await cheerio.load(bodyHTML);

    jsonframe($)

    let frame = {
        hotels : {
            _s : "[itemtype='https://schema.org/Hotel']",
            _d : [{
                "hotelname" : "h3[itemprop='name']>span.item-link",
                "hotelprice": "meta[itemprop='price'] ~ em ~ strong"
            }]
        }
    };

    const displayResult = $('body').scrape(frame, { string: true } );

    if (displayResult.length > 0) {
        const responseCode = '200';
        const server = http.createServer(function(req,res){
            res.writeHead(responseCode, {'Content-Type': 'application/json; charset=utf-8'});
            res.end(displayResult);
        }).listen(3000);

        console.log('Node Server running on localhost:3000');
    } else {
        console.log('Node Server cannot running, because results cannot be parsed.')
    }

})();

...