Как рекурсивно сканировать страницу, очищать ссылки, переходить по ссылкам, затем снова очищать и экспортировать в node js?

#javascript #node.js #recursion #web-scraping

#javascript #node.js #рекурсия #веб-очистка

Вопрос:

Пока я могу заставить свой код экспортировать ссылки на первой странице, но у меня возникают проблемы с вставкой ссылок на последующие страницы. Я просто хочу, чтобы он углубился в поиск, просто перейдите по ссылкам один раз, очистите ссылки и вставьте в мой массив объектов, а затем экспортируйте в файл json. Может кто-нибудь, пожалуйста, скажите мне, чего не хватает в моей функции?

 const cheerio = require('cheerio');
const fs = require('fs');
const chalk = require('chalk');
const axios = require('axios');

const START_URL = 'https://www.reddit.com/r/Frontend/';
const outputFile = 'data.json';
var results = {};
results.sites = [];

var pagesVisited = {};
var numPagesVisited = 0;
var pagesToVisit = [];
var url = new URL(START_URL);
var baseUrl = url.protocol   '//'   url.hostname;
var MAX_PAGES_TO_VISIT = 1;

pagesToVisit.push(START_URL);

const crawl = () => {
  if (numPagesVisited >= MAX_PAGES_TO_VISIT) {
    console.log('Reached max limit of number of pages to visit.');
    return;
  }
  var nextPage = pagesToVisit.pop();
  if (nextPage in pagesVisited) {
    // We've already visited this page, so repeat the crawl
    crawl();
  } else {
    // New page we haven't visited
    collectURLS(nextPage, crawl);
  }
};

const collectURLS = async (url, callback) => {
  pagesVisited[url] = true;
  numPagesVisited  ;

  const { data } = await axios.get(START_URL);
  const $ = cheerio.load(data);

  if (results === null) {
    $("a[href^='http']").each((i, elem) => {
      const link = $(elem).attr('href');
      pagesToVisit.push(baseUrl   $(this).attr('href'));
      if (results === null) {
        var obj = {
          url: link,
          links: [],
        };
        results.sites.push(obj);
        callback();
      }
    });
  } else if (results !== null) {
    $("a[href^='http']").each((i, elem) => {
      const link = $(elem).attr('href');
      results.sites.links.push(link);
    });
  }
  exportResults();
};

//Export results object to json file
const exportResults = () => {
  fs.writeFile(outputFile, JSON.stringify(results, null, 4), function (err) {
    if (err) throw err;
    console.log('complete');
  });
  console.log(
    chalk.black.bgWhite(
      `n ${chalk.underline.bold(
        results.length
      )} Results exported successfully to ${chalk.underline.bold(outputFile)}n`
    )
  );
};

crawl();

 

Я хочу, чтобы мой вывод выглядел так

 {
 "sites": [
{
 "url1": "holds this pages link and was scraped from original URL",
"links": [where this URLs scraped links will go]
}
{
"url2": "holds this pages link and was scraped from original URL",
"links": [where this URLs scraped links will go]
}
.
.
.
]
}
 

Комментарии:

1. Это на самом деле то, с чем вы работали: var MAX_PAGES_TO_VISIT = 1; ? Потому что это многое объяснило бы!

2. да, я запускал его только с этим, но это не оригинальная версия, которая работала

Ответ №1:

Я бы начал с этого, потому что за этим гораздо проще следить:

 const crawl = async () => {
  var nextPage
  while (nextPage = pagesToVisit.pop()) {
    await collectURLS(nextPage)
  }
  exportResults()
}
 

Также убедитесь, что не используйте this функции со стрелками, если вы не понимаете разницу с обычными функциями.