Node.js网页抓取问题|要求| cheerio

时间:2017-01-22 03:53:27

标签: javascript node.js

我正在使用Node.js和请求模块以及cheerio模块编写一个相当简单的Web scraper。 我的代码无法正常工作有两个原因:

  1. 当我试图刮取图片网址时,每个网页只会多次返回一个网址。
  2. 每个'href'和'title'的迭代以看似随机的顺序发生(每次都是相同的顺序,但仍然没有按顺序,例如1,2,3等)。
  3. 这是我的代码:

    var request = require('request'),
        cheerio = require('cheerio');
    
    var sqlite3 = require('sqlite3').verbose();
    var database = "storage.db"
    console.log('[+] Creating database: ' + database);
    var db = new sqlite3.Database(database);
    
    var pw_url = "https://primewire.unblocked.ink"
    
    console.log('[+] Creating table with rows...');
    db.serialize(function() {
      db.run("CREATE TABLE IF NOT EXISTS main (title TEXT, film_page_links TEXT, img_url TEXT)");
    });
    
    var img_urls = {}
    
    function iter_pages(page_number) {
      request(pw_url + '/index.php?sort=featured&page=' + page_number, function(err, resp, body) {
        if(!err && resp.statusCode == 200) {
          console.log('[+] The request response status code is: ' + resp.statusCode);
          var $ = cheerio.load(body);
          console.log('[+] Inserting values into database.');
          $('.index_item a img', '.index_container').each(function() {
            img_urls.img_url = $(this).attr('src');
          });
          $('.index_item a', '.index_container').each(function() {
            var url = $(this).attr('href');
            var title = $(this).attr('title');
            if(url.startsWith('/watch-')) {
              //urls.push('https://primewire.unblocked.ink' + url);
              db.run("INSERT INTO main (title, film_page_links, img_url) VALUES (?, ?, ?)",
                      title.replace("Watch ", ""),
                      pw_url + url,
                      "https:" + img_urls.img_url);
            };
          });
          console.log('[+] Processed page:' + page_number);
        }
      });
    }
    
    for (var i = 1; i < 5; i++) {
        iter_pages(i);
    }
    

    这是我的console.log:

    [+] Creating database: storage.db
    [+] Creating table with rows...
    [+] The request response status code is: 200
    [+] Inserting values into database.
    [+] Processed page:4
    [+] The request response status code is: 200
    [+] Inserting values into database.
    [+] Processed page:1
    [+] The request response status code is: 200
    [+] Inserting values into database.
    [+] Processed page:3
    [+] The request response status code is: 200
    [+] Inserting values into database.
    [+] Processed page:2
    

    正如你所看到的那样顺序是4,1,3,2,这让我很困惑。

    它返回的图像网址始终是每个页面的第21项。

    我是JavaScript的新手,所以请善待,我已经尝试移动方法,在iter_pages函数中获取图像URL,这会破坏代码或返回相同的东西。

    即使是更高级教程的链接也足够了,我学习的东西非常快,但问题是我发现的所有教程都只是非常基本的技术。

1 个答案:

答案 0 :(得分:1)

第一个问题:

这是您设置图片网址的方式:img_urls.img_url = ...

发生的事情是,每当你设置时,你将它放在同一个属性中并覆盖那里的内容,这就是为什么它始终是页面中的最后一个。您可以尝试通过推入数组来修复它,但由于您有两个循环,它会使事情变得更复杂,而是尝试在同一个循环中执行这两个循环:

 $('.index_item a', '.index_container').each(function() {
    var url = $(this).attr('href');
    var title = $(this).attr('title');
    var img_url = $('img', this).attr('src');
    if(url.startsWith('/watch-')) {
      //urls.push('https://primewire.unblocked.ink' + url);
      db.run("INSERT INTO main (title, film_page_links, img_url) VALUES (?, ?, ?)",
              title.replace("Watch ", ""),
              pw_url + url,
              "https:" + img_url);
    };
  });

第二个问题:

你需要实现几件事。 request(...)正在发出异步网络请求。这意味着此功能立即完成,结果尚未到达。因此循环继续进行并且所有网络请求同时开始,但是由于许多不同的变量和运气,一些网络请求在不同时间完成。有些可能更快,有些更慢。由于它们几乎都是在同一时间开始的,因此它们的启动顺序并不重要。这里简化了您的问题:

const request = require('request');

for (let i = 0; i < 5; i++) { 
  makeRequest(i);
}

function makeRequest(i) {
  console.log('Starting', i);
  console.time(i);
  request('http://google.com', () => console.timeEnd(i));
}

以下是日志:

$ node a.js
Starting 0
Starting 1
Starting 2
Starting 3
Starting 4
1: 8176.111ms
2: 8176.445ms
3: 8206.300ms
0: 8597.458ms
4: 9112.237ms

再次运行它会产生这样的结果:

$ node a.js
Starting 0
Starting 1
Starting 2
Starting 3
Starting 4
3: 8255.378ms
1: 8260.633ms
2: 8259.134ms
0: 8268.859ms
4: 9230.929ms

所以你可以看到订单不是确定性的。只有一些完成得比其他人快。

如果你真的希望它们按顺序发生,我建议使用控制流程库。 async.js是最受欢迎的广告之一。