2017-01-22 51 views
1

我正在写一个相当简单的使用Node.js和请求模块和cheerio模块的网络抓取工具。 我所想要的,原因有两个我的代码不工作:Node.js Web抓取问题|请求| cheerio

  1. 当试图刮掉图像URL我只与单个URL多次为每个页面返回。
  2. 每个“HREF”和“标题”的迭代发生在一个看似随机的顺序(它是相同的顺序中的每个的时间,但仍没有为了例如1,2,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,它混淆了我。

图像URL返回始终是每一页的21项。

我是新来的JavaScript,请善待,我已经试过移动方法的iter_pages功能,无论是打破了代码或返回同样的事情中取周围的图像的URL。

即使到更先进的教程就足够了一个链接,我学东西非常快,但问题是,我发现所有的教程只是非常基本的技术。

回答

1

第一个问题:

这是你如何设置图像的URL: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是最受欢迎的之一。

+0

哇,谢谢Farid,问题1解决了 - 太棒了!我不知道以'$('img',this)'这样的方法获取img标签。我现在将着手解决您的建议中的问题二。这是一个明确的选择答案谢谢你又:) –