私はDOMを解析するために使用nodeJS
するWebスクレイパーを構築しています。を使用していますが、これは一般的な質問だと思います。request
cheerio
node
javascript
tl;dr - ~60,000 から 100,000 個のオブジェクトを作成し、コンピューターの RAM をすべて使い果たし、out of memory
ノードでエラーが発生します。
スクレーパーの仕組みは次のとおりです。これはループ内のループです。これほど複雑なものをこれまで設計したことがないため、これを行うためのより良い方法があるかもしれません。
ループ 1:「sitesArr」という配列に 10 個のオブジェクトを作成します。各オブジェクトは、スクレイピングする 1 つの Web サイトを表します。
var sitesArr = [
{
name: 'store name',
baseURL: 'www.basedomain.com',
categoryFunct: '(function(){ // do stuff })();',
gender: 'mens',
currency: 'USD',
title_selector: 'h1',
description_selector: 'p.description'
},
// ... x10
]
ループ 2:「sitesArr」をループします。各サイトについて、「リクエスト」経由でホームページにアクセスし、通常 30 ~ 70 個の URL のカテゴリ リンクのリストを取得します。これらの URL を、それらが属する現在の「sitesArr」オブジェクトに、名前が「categories」である配列プロパティに追加します。
var sitesArr = [
{
name: 'store name',
baseURL: 'www.basedomain.com',
categoryFunct: '(function(){ // do stuff })();',
gender: 'mens',
currency: 'USD',
title_selector: 'h1',
description_selector: 'p.description',
categories: [
{
name: 'shoes',
url: 'www.basedomain.com/shoes'
},{
name: 'socks',
url: 'www.basedomain.com/socks'
} // x 50
]
},
// ... x10
]
ループ 3:各「カテゴリ」をループします。URL ごとに製品リンクのリストを取得し、それらを配列に入れます。通常、カテゴリごとに約 300 ~ 1000 個の製品
var sitesArr = [
{
name: 'store name',
baseURL: 'www.basedomain.com',
categoryFunct: '(function(){ // do stuff })();',
gender: 'mens',
currency: 'USD',
title_selector: 'h1',
description_selector: 'p.description',
categories: [
{
name: 'shoes',
url: 'www.basedomain.com/shoes',
products: [
'www.basedomain.com/shoes/product1.html',
'www.basedomain.com/shoes/product2.html',
'www.basedomain.com/shoes/product3.html',
// x 300
]
},// x 50
]
},
// ... x10
]
ループ 4:各「products」配列をループし、各 URL に移動して、それぞれのオブジェクトを作成します。
var product = {
infoLink: "www.basedomain.com/shoes/product1.html",
description: "This is a description for the object",
title: "Product 1",
Category: "Shoes",
imgs: ['http://foo.com/img.jpg','http://foo.com/img2.jpg','http://foo.com/img3.jpg'],
price: 60,
currency: 'USD'
}
次に、製品オブジェクトごとupsert
に、データベースに変換する MongoDB 関数に出荷しています。
問題
プロセスが大きくなるまで、これはすべてうまくいきました。このスクリプトを実行するたびに約 60,000 個の製品オブジェクトを作成していますが、しばらくするとコンピューターの RAM がすべて使い果たされます。さらに、プロセスの途中で次のエラーが発生しNode
ます。
FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory
これはコード設計の問題であると私は非常に考えています。オブジェクトを使い終わったら、オブジェクトを「削除」する必要がありますか? これに取り組む最善の方法は何ですか?