Невозможно использовать ссылки для получения разных заголовков. - PullRequest
2 голосов
/ 15 апреля 2019

Я создал скрипт в node, используя promise в сочетании с request и cheerio, чтобы проанализировать столбец links под Province из этой веб-страницы и затем использовать ихссылки для очистки всех URL-адресов в столбце Office от всех таких страниц и, наконец, использования этих links для сбора title со всех таких целевых страниц , какв Cairos main Post Office на этой странице.

Мой текущий скрипт в большинстве случаев застревает.Однако иногда выдает эту ошибку UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'parent' of undefined.Я проверил каждую из функций и обнаружил, что все они работают правильно по отдельности.

Хотя скрипт выглядит немного больше, он построен на очень простой логике, использующей каждую links с целевой страницы, пока не достигнет title целевой страницы.

Это моя попытка:

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

const link = 'https://www.egyptcodebase.com/en/p/all';
const base_link = 'https://www.egyptcodebase.com/en/';

const items = [];
const nitems = [];

let getLinks = () => {
    return new Promise((resolve, reject) => {
        request(link, function(error, response, html) {
            let $ = cheerio.load(html);
            if (error) return reject(error);
            try {
                $('.table tbody tr').each(function() {
                    items.push(base_link + $(this).find("a").attr("href"));
                });
                resolve(items);
            } catch (e) {
                reject(e);
            }
        });
    });
};

let getData = (links) => {
    const promises = links
        .map(nurl => new Promise((resolve, reject) => {
            request(nurl, function(error, response, html) {
                let $ = cheerio.load(html);
                if (error) return reject(error);
                try {
                    $('.table tbody tr').each(function() {
                        nitems.push(base_link + $(this).find("a").attr("href"));
                    });
                    resolve(nitems);
                } catch (e) {
                    reject(e);
                }
            })
        }))

    return Promise.all(promises)
}

let FetchData = (links) => {
    const promises = links
        .map(nurl => new Promise((resolve, reject) => {
            request(nurl, function(error, response, html) {
                let $ = cheerio.load(html);
                if (error) return reject(error);
                try {
                    resolve($(".home-title > h2").eq(0).text());
                } catch (e) {
                    reject(e);
                }
            })
        }))

    return Promise.all(promises)
}

getLinks().then(resultList => {
    getData(resultList).then(resultSet => {
        FetchData(resultSet).then(title =>{
            console.log(title);
        })
    })
})

Какможно ли вычеркнуть заголовки с целевых страниц, используя все ссылки с целевых страниц?

Ответы [ 3 ]

3 голосов
/ 29 апреля 2019

Было бы намного проще спросить владельца сайта о необходимых вам данных.
Он может понять вашу просьбу и дать ее вам бесплатно, вместо того, чтобы просматривать свой сайт.

П.С .: Я с удивлением обнаружил вопрос о том, как отказаться от моего собственного сайта.
P.S2: Если вам просто нужны все названия почтовых отделений, я бы дал их вам бесплатно: D
P.S3: Ваша ошибка, возможно, происходит из-за того, что некоторое время на странице нет элемента, который вы пытаетесь проанализировать с помощью cheerio.

1 голос
/ 02 мая 2019

Итак, проблема в массиве 2D.Если вы внимательно изучите функцию getData, вы вернете 2D-массив.

map верните массив, и в этой карте вы решите другой массив nitems.

* 1008.* Вот рабочий код:
const base_link = 'https://www.egyptcodebase.com/en/';

// helper wrapper DRY
const getHtmls = (url) => {
  return new Promise((resolve, reject) => {
    request({ uri: url, method: 'GET', followAllRedirects: true } , function(error, response, html) {
      if (error) reject(error);
      else resolve(html);
    });
  })
}

let getLinks = async () => {
  const link = 'https://www.egyptcodebase.com/en/p/all';
  const items = [];
  try {
    const html = await getHtmls(link);
    let $ = cheerio.load(html);
    $('.table tbody tr').each(function() {
      items.push(base_link + $(this).find("a").attr("href"));
    });
  } catch (e) {
    // handling error here so execution can continue for good eggs
    console.error(e.message)
  }
  return items;
};

let getData = async (links) => {
  const out = [];
  try {
    const promises = links.map(nurl => getHtmls(nurl));

    const htmls = await Promise.all(promises);
    htmls.forEach(html => {
      let $ = cheerio.load(html);
      $('.table tbody tr').each(function() {
        out.push(base_link + $(this).find("a").attr("href"));
      });
    })
  } catch (e) {
    // handling error here so execution can continue for good eggs
    console.error(e.message)
  }
  return out;
}

let FetchData = async (links) => {
  const out = [];
  try {
    const promises = links.map(nurl => getHtmls(nurl));
    const htmls = await Promise.all(promises)
    htmls.forEach(html => {
      try {
        let $ = cheerio.load(html);
        out.push($(".home-title > h2").eq(0).text());
      } catch (e){
        // handling error here so execution can continue for good eggs
        console.error(e.message)
      }
    })
  } catch (e) {
    // handling error here so execution can continue for good eggs
    console.error(e.message)
  }
  return out;
}

getLinks().then(resultList => {
  getData(resultList).then(resultSet => {
    FetchData(resultSet).then(title =>{
      console.log(title);
    })
  })
})

Примечание. Вместо написания собственной оболочки Promise вы можете использовать request-promise package

0 голосов
/ 25 апреля 2019

Проблема с вашим кодом в функции FetchData, так как в этой функции вы передаете ссылки, а затем используете карту поверх них.Но если вы загляните внутрь этой функции карты и проверите значение переменной 'nurl', это будет массив ссылок, а его тип данных будет object.В соответствии с семантикой функции запроса, ее первый параметр должен быть строкой, поэтому, если вы перебираете переменную 'nurl' для получения значений, это будет работать.

Мой фрагмент кода для одного URLиз массива

...