2

私はDOMを解析するために使用nodeJSするWebスクレイパーを構築しています。を使用していますが、これは一般的な質問だと思います。requestcheerionodejavascript

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

これはコード設計の問題であると私は非常に考えています。オブジェクトを使い終わったら、オブジェクトを「削除」する必要がありますか? これに取り組む最善の方法は何ですか?

4

0 に答える 0