【问题标题】:Using FS to write new files if a certain url is found and remove the file if it's not found anymore如果找到某个 url,则使用 FS 写入新文件,如果不再找到,则删除该文件
【发布时间】:2020-08-06 12:14:00
【问题描述】:

我正在尝试编写一个脚本,当找到一个新的 url 时,它会将 url 转换为哈希。检查文件是否已经被写入,它会忽略它,如果之前不知道它应该被添加。

needle.get(mainUrl, function(err, res) {
  if (err) throw err;

  if (res.statusCode == 200 && !err ) {
    var $ = cheerio.load(res.body)

    var href = $('div div a').each(function(index, element) {
      urlList.push($(element).attr("href"))

      var url =($(element).attr("href"))
      var hash = crypto.createHash('md5').update(url).digest('hex');
                
      fs.writeFile('./directory/otherdirectory' + `${hash}`, url, (err) => {
        if (err) throw err;
        console.log('Hash created: ' + url + ' saved as ' + hash
      });
    }
  )
}
})

这是我到目前为止所做的,但这只会写入新文件。它不会检查是否已添加文件,也不会删除不再找到的文件。

所以我想做什么:

  1. 我编写了一个脚本,用于获取网站的网址。
  2. 散列所有网址。
  3. 让 FS 检查文件是否已经被写入,如果它只是忽略它。
  4. 如果之前不知道,请将其添加为新文件。
  5. 如果在获取时找不到 url,请将其从列表中删除。

【问题讨论】:

  • 最后一点“如果在获取时找不到url,则从列表中删除它”会很棘手。该目录是否仅包含相关文件到同一个网站?同样从事物的外观来看,可能有更好的方法来做到这一点,所以如果你能解释你在这里想要做什么以及为什么,那就太好了
  • @ibrahimmahrir 我想在获取同一个网站时使用它。因此,在网站上找到的每个 url 都将被添加到列表中,因此只有来自同一网站的 url,但是一旦在该网站上找不到该 url,就需要将其删除。所以我只会存储来自一个网站的网址。所以是的,只来自一个网站。
  • 为什么不使用文本文件来存储 url 而不是将它们存储在单独的文件中?这样会干净很多。
  • @ibrahimmahrir 老实说我还没想过,它会更快吗?
  • 是的,因为您将只处理一个文件并且您不需要哈希。也会更短。您是在保存有关 url 的额外数据,还是只保存 url?另外,您是否在其他地方使用这些网址?

标签: javascript web-scraping fs cheerio


【解决方案1】:

我认为这可能是X/Y problem,为此我仍在等待my comment 的答复。

话虽如此,您可以简单地使用fs.existsSync 忽略现有文件,如果返回true,则跳过保存当前文件,否则保存它。要删除不再可用的文件,只需使用 fs.readdir 获取目录中的所有文件,然后使用 fs.unlink 删除您的 url 不在响应中的文件:

needle.get(mainUrl, (err, res) => {
  if (err) throw err;

  if (res.statusCode == 200) {
    let $ = cheerio.load(res.body);

    let hashes = [];                                                      // list of hashes for this website (to be used later to keep only the items that are still available)
    $('div div a').each((index, element) => {
      let url = $(element).attr("href");
      let hash = crypto.createHash('md5').update(url).digest('hex');
      hashes.push(hash);                                                 // store the hash of the current url
      
      if (!fs.existsSync('./directory/otherdirectory/' + hash)) {        // if this file doesn't exist (notice the "not operator !" before fs.existsSync)
        fs.writeFile('./directory/otherdirectory/' + hash, url, err => { // save it
          if (err) throw err;
          console.log('Hash created: ' + url + ' saved as ' + hash);
        });
      }
    });

    fs.readdir('./directory/otherdirectory', (err, files) => {           // get a list of all the files in the directory
      if (err) throw err;
      files.forEach(file => {                                            // and for each file
        if(!hashes.includes(file)) {                                     // if it was not encountered above (meaning that it doesn't exist in the hashes array)
          fs.unlink('./directory/otherdirectory/' + file, err => {       // remove it
            if (err) throw err;
          });
        }
      });
    });
});

另一种方法:

由于您似乎只想存储 url,因此最好的方法是使用一个文件来存储它们,而不是将每个 url 存储在自己的文件中。像这样更有效:

needle.get(mainUrl, (err, res) => {
  if (err) throw err;

  if (res.statusCode == 200) {
    let $ = cheerio.load(res.body);

    let urls = $('div div a')                                           // get the 'a' elements
      .map((index, element) => $(element).attr("href"))                 // map each one into its href attribute
      .get();                                                           // and get them as an array
        
    fs.writeFile('./directory/list-of-urls', urls.join('\n'), err => {  // then save all the urls encountered in the file 'list-of-urls' (each on its own line, hence the join('\n'))
      if (err) throw err;
      console.log('saved all the urls to the file "list-of-urls"');
    });
  }
});

这样,每次文件都被覆盖时,旧的 url 将被自动删除,新的 url 将被自动添加。无需检查是否已遇到 url,因为无论如何它都会被重新保存。

如果您想在其他地方获取 url 列表,只需读取文件并将其拆分为 '\n',如下所示:

 fs.readFile('./directory/list-of-urls', 'utf8', (err, data) => {
   if (err) throw err;
   let urls = data.split('\n');
   // use urls here
 });

【讨论】:

    猜你喜欢
    • 2022-01-19
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 2014-02-28
    • 1970-01-01
    相关资源
    最近更新 更多