簡體   English   中英

Node.js 網頁抓取問題 | 請求 | 啦啦隊

[英]Problems with Node.js web scraping | request | cheerio

我正在使用 Node.js 和 request 模塊以及cheerio 模塊編寫一個相當簡單的網絡爬蟲。 我的代碼無法正常工作,原因有兩個:

  1. 當嘗試抓取圖像 url 時,我只為每個頁面多次返回一個 url。
  2. 每個 'href' 和 'title' 的迭代以看似隨機的順序發生(每次都是相同的順序,但仍然沒有順序,例如 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 的方法,這會破壞代碼或返回相同的內容。

即使是更高級教程的鏈接也足夠了,我學東西很快,但問題是我發現的所有教程都只是非常基本的技術。

第一個問題:

這是您設置圖像 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是最受歡迎的之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM