我創建了一個腳本,使用request和cheerio庫,從這個網頁中抓取不同省份的鏈接,然后使用這些urls來決議這里中不同辦事處的鏈接。最后,使用這些辦事處的鏈接從這里中刮取標題。
當我運行該腳本時,我可以看到它一直在做相應的作業,直到它在執行的某個地方被卡住。當它被卡住時,它并沒有拋出任何錯誤。
下面是一些步驟。
以下是腳本所遵循的圖片步驟:
以下是我所嘗試的內容:
const request = require('request') 。
const cheerio = require('cheerio') 。
const link = 'https://www.egyptcodebase.com/en/p/all';
const base_link = 'https://www.egyptcodebase.com/en/'。
let getLinks=(link)=> {
const items = [];
return new Promise((resolve, reject) => /span> {
request(link, function(error, response, html) {
let $ = cheerio.load(html)。
if (error) return reject(error)。
try {
$('.table tbody tr').each(function() {
items.push(base_link $(this) 。 find("a[href]").attr("href") )。
});
resolve( items)。
} catch (e) {
reject(e);
}
});
});
};
let getData = (links) => {
const nitems = [];
const promises = links
. map(span class="hljs-params">nurl => new Promise((resolve, reject) =>;{
request(nurl, function(error, response, html) {
let $ = cheerio.load(html)。
if (error) return reject(error)。
try {
$(' .table tbody tr').each(function() {
nitems.push(base_link $(this) 。 find("a[href]").attr("href") )。
});
resolve(nitems)。
} catch (e) {
reject(e)。
}
})
}))
return Promise.all(promises)
}
let FetchData = (links) => {
const promises = links
. map(turl => new Promise((resolve, reject) =>;{
request(turl, function(error, response, html) {
if (error) return reject(error)。
let $ = cheerio.load(html);
try {
const title = $(".home-title > h2") 。 eq(0).text()。
console.log( {
title: title,
itemLink: turl
});
resolve(標題)。
} catch (e) {
reject(e)。
}
})
}))
return Promise.all(promises)
}
(async function main(){
const result = await getLinks(link)。
const resultSecond = await getData(result)。
const merged = resultSecond.flat(1) 。
const resultFinal = await FetchData(merged)。
for (const title of resultFinal) {
console.log(標題)。
}
})().catch(console.error)。
如何使腳本完成它的執行程序?
<PS 雖然這個腳本看起來很大,但是其中使用的函式除了選擇器之外,其他的幾乎都是一樣的。
uj5u.com熱心網友回復:
好的,所以在測驗這段代碼時,我一開始就遇到了兩個問題:
resultSecond,包含getData()的資料,回傳一個類似陣列的物件,而不是一個陣列,所以我無法使用flat()。因此,我創建了一個將物件轉換為陣列的函式toArray,并在resultSecond之后添加了一個名為resultThird的變數,并對resultSecond使用該函式,將其變成一個陣列。
flat()在陣列原型中不存在,所以我不得不手動添加它。
在解決了這些問題之后,我能夠運行你的代碼,并經歷了你所說的掛起的情況。
發生了一個ECONNRESET錯誤,然后在掛起之前繼續進行了大概幾千個請求。ECONNRESET通常是由于沒有處理異步網路錯誤或你所請求的服務器決定關閉連接。不確定請求模塊將如何處理這樣的事件,但似乎該模塊有可能沒有正確處理網路錯誤或終止連接。
問題是你向這個網站的 API 發出了 15,000 個請求,因此 API 可能有一個速率限制器,看到了請求的數量并終止了其中的大部分,但允許幾千個請求通過,但由于你沒有處理終止的連接--很可能是由于請求模塊吞噬了這些錯誤--它被 "掛 "在那里,節點行程沒有退出。
因此,我使用異步模塊將請求劃分為 300 個間隔,并且作業得非常順利。沒有終止連接,因為我沒有達到速率限制。你也許可以將間隔限制提高到300以上。
然而,我建議不要使用 request 模塊,而使用另一個 http 模塊,如 axios,它很可能會處理這些問題。當你要做大量的異步請求時,你應該考慮使用async。它有很多有用的方法。如果你需要更多解釋async模塊在這里做什么,請聯系我,但我建議先閱讀檔案。https://caolan.github.io/async/v3/docs.html#mapLimit
const request = require('request') 。
const cheerio = require('cheerio') 。
const _async = require('async')。
const link = 'https://www.egyptcodebase.com/en/p/all';
const base_link = 'https://www.egyptcodebase.com/en/'。
const toArray = (obj) => {
const arr = [];
for (const prop in obj) {
arr.push(obj[prop] )
}
return arr;
}
Object.defineProperty(Array. prototype, 'lat', {
value: function(depth = 1) {
return this.reduce(function (flat,toFlatten) {
return flat.concat((Array. isArray(toFlatten) && (depth>1)) ? toFlatten.flat(depth-1) : toFlatten) 。
}, []);
}
});
let getLinks = (link)=> {
const items = [];
return new Promise((resolve, reject) => /span> {
request(link, function(error, response, html) {
let $ = cheerio.load(html)。
if (error) return reject(error)。
try {
$('.table tbody tr').each(function() {
items.push(base_link $(this) 。 find("a[href]").attr("href") )。
});
resolve( items)。
} catch (e) {
reject(e);
}
});
});
};
let getData = (links) => {
const nitems = [];
const promises = links
. map(span class="hljs-params">nurl => new Promise((resolve, reject) =>;{
request(nurl, function(error, response, html) {
let $ = cheerio.load(html)。
if (error) return reject(error)。
try {
$(' .table tbody tr').each(function() {
nitems.push(base_link $(this) 。 find("a[href]").attr("href") )。
});
return resolve(nitems)。
} catch (e) {
return reject(e)。
}
})
}))
return Promise.all(promises)
}
let FetchData = (links) => {
const limit = 300;
return new Promise((resolve, reject) => /span> {
const itr = (col, cb) =>{
request(col, function(error, response, html){
if (error) cb(error)
let $ = cheerio.load(html);
try {
const title = $(".home-title > h2") 。 eq(0).text()。
console.log( {
title: title,
itemLink: col
});
cb(null, title)。
} catch (e) {
cb(e)。
}
})
}
_async.mapLimit(link, limit, itr, function(err, results) {
if (err) reject(err)。
return resolve(results)。
})
})
}
(async function main() {
const result = await getLinks(link)。
const resultSecond = await getData(result)。
const resultThird = toArray(resultSecond)。
const merged = resultThird.flat(1) 。
const resultFinal = await FetchData(merged)。
for (const title of resultFinal) {
console.log("title: ", title);
}
})().catch(span class="hljs-params">err => console.log(err)
//good to listen to these[/span]。
process.on('uncaughtException', err => { console. log(err) }) 。
process.on('unhandledRejection', err => { console. log(err) })。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/320251.html
標籤:
