Как получить элемент из нескольких URL, добавляя каждый? - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть веб-сайт с основным URL-адресом, содержащим несколько ссылок. Я хочу получить первый <p> элемент из каждой ссылки на этой главной странице.

У меня есть следующий код, который отлично работает, чтобы получить нужные ссылки с главной страницы и сохранить их в массиве urls. Но моя проблема в том, что я не знаю, как заставить al oop загружать каждый URL из массива urls и печатать каждый first <p> в каждой итерации или добавлять их в переменную и печатать все в конце.

Как я могу это сделать? спасибо

var request = require('request');
var cheerio = require('cheerio');

var main_url = 'http://www.someurl.com';

request(main_url, function(err, resp, body){
$ = cheerio.load(body);
links = $('a'); //get all hyperlinks from main URL
var urls = [];

//With this part I get the links (URLs) that I want to scrape.
$(links).each(function(i, link){
    lnk = 'http://www.someurl.com/files/' + $(link).attr('href');
    urls.push(lnk);
});

//In this part I don't know how to make a loop to load each url within urls array and get first <p>
    for (i = 0; i < urls.length; i++) { 

        var p = $("p:first") //first <p> element
        console.log(p.html());
    }
});

1 Ответ

1 голос
/ 09 апреля 2020

Если вы можете успешно получить URL-адреса с первого <p>, вы уже знаете все, что нужно для этого, поэтому я полагаю, у вас есть проблемы с работой request и, в частности, с рабочим процессом на основе обратного вызова.

Я предлагаю отказаться от request, так как он устарел. Вы можете использовать что-то вроде got , основанное на Promise, так что вы можете использовать более новые функции async / await, которые идут с ним (что обычно означает более легкий рабочий процесс) (хотя вам нужно использовать по крайней мере nodejs 8 тогда!).

Ваш l oop будет выглядеть так:

for (const i = 0; i < urls.length; i++) {
  const source = await got(urls[i]);
  // Do your cheerio determination
  console.log(new_p.html());
}

Имейте в виду, что сигнатура вашей функции должна быть скорректирована. В вашем случае вы вообще не указали функцию, поэтому используется сигнатура функции модуля, что означает, что вы не можете использовать await. Поэтому напишите для этого функцию:

async function pullAllUrls() {
  const mainSource = await got(main_url);
  ...
}

Если вы не хотите использовать async / await, вы можете работать с некоторыми сокращениями обещаний, но, на мой взгляд, это довольно громоздко. Затем вместо go вернитесь к обещаниям и используйте библиотеку рабочих процессов, такую ​​как asyn c, чтобы помочь вам управлять извлечением URL.

Реальный пример с async / await:

В примере из реальной жизни я бы создал функцию для извлечения источника страницы, которую я хотел бы получить, например, так (не забудьте добавить get в ваш скрипт / пакет. json):

async function getSourceFromUrl(thatUrl) {
  const response = await got(thatUrl);
  return response.body;
}

Тогда у вас есть логика рабочего процесса c, чтобы получить все эти ссылки на другой странице. Я реализовал это так:

async function grabLinksFromUrl(thatUrl) {
  const mainSource = await getSourceFromUrl(thatUrl);
  const $ = cheerio.load(mainSource);
  const hrefs = [];

  $('ul.menu__main-list').each((i, content) => {
    $('li a', content).each((idx, inner) => {
      const wantedUrl = $(inner).attr('href');
      hrefs.push(wantedUrl);
    });
  }).get();

  return hrefs;
}

Я решил, что хотел бы получить ссылки в элементе <nav>, которые обычно заключены в <ul> и элементы <li>. Итак, мы просто возьмем их.

Тогда вам нужен рабочий процесс для работы с этими ссылками. Вот где for l oop. Я решил, что мне нужен заголовок каждой страницы.

async function mainFlow() {
  const urls = await grabLinksFromUrl('https://netzpolitik.org/');
  for (const url of urls) {
    const source = await getSourceFromUrl(url);

    const $ = cheerio.load(source);
    // Netpolitik has two <title> in their <head>
    const title = $('head > title').first().text();
    console.log(`${title} (${url}) has source of ${source.length} size`);

    // TODO: More work in here
  }
}

И, наконец, вам нужно вызвать эту функцию рабочего процесса:

return mainFlow();

Результат, который вы видите на экране, должен выглядеть следующим образом это:

Dossiers & Recherchen (https://netzpolitik.org/dossiers-recherchen/) has source of 413853 size
Der Netzpolitik-Podcast (https://netzpolitik.org/podcast/) has source of 333354 size
14 Tage (https://netzpolitik.org/14-tage/) has source of 402312 size
Official Netzpolitik Shop (https://netzpolitik.merchcowboy.com/) has source of 47825 size
Über uns (https://netzpolitik.org/ueber-uns/#transparenz) has source of 308068 size
Über uns (https://netzpolitik.org/ueber-uns) has source of 308068 size
netzpolitik.org-Newsletter (https://netzpolitik.org/newsletter) has source of 291133 size
netzwerk (https://netzpolitik.org/netzwerk/?via=nav) has source of 299694 size
Spenden für netzpolitik.org (https://netzpolitik.org/spenden/?via=nav) has source of 296190 size
...