1

私はウェブサイト用に半作業スクレイピングスクリプトを書きました:

async function pageFunction(context) {
    const {
        request,
        log,
        skipLinks,
        jQuery: $,
        waitFor
    } = context;

        log.info('Pagination');
        let timeoutMillis; // undefined
        const buttonSelector = 'div.pagination-view-more';

        //click on Show more button 5 times
        for (let step = 0; step < 5; step++) {
            log.info('Waiting for the "Show more" button.');
            try {
                await waitFor(buttonSelector, {
                    timeoutMillis
                }); // Default timeout first time.
                timeoutMillis = 5000; // 2 sec timeout after the first.
            } catch (err) {
                // Ignore the timeout error.
                log.info('Could not find the "Show more button", we\'ve reached the end.');
                break;
            }
            log.info('Clicking the "Show more" button.');
            $(buttonSelector).click();
        }

        //export the results
        var result = [];
        $(".thing-card").each(function() {
            result.push({
                title: $(this).attr('title'),
                //format Dec 15, 2019
                date: $(this).find('.item-header .item-date').text().replace(/\s/g, ''),
            });
        });
        return result;

}

上記の例では、[もっと見る] ボタンを 5 回クリックして、結果としてタイトルと日付をエクスポートしようとしています。問題は、すべての結果が得られないことです。スクリプトが本来よりも早く終了していると思います。

最後のスクリプトでは、修正された for ループを削除し、結果からの日付が今日から最大 -7 日 (または 1 週間) になるまでこのループを実行したいと思います。これは何とかApifyで可能ですか?

4

1 に答える 1

0

私はあなたがこれをほとんど持っていると思います。必要なコードを記述できるため、Apify には制限がありません :) したがって、これは Apify に固有のものというよりも、より一般的な JS の質問です。

固定ループの代わりに、最後のアイテムの日付を確認できます (アイテムは最新のものからソートされていると想定しています)。

あなたはそれを微調整することができますが、このような何かがそれを行うべきです。

async function pageFunction(context) {
    const {
        log,
        jQuery: $,
        waitFor
    } = context;

    log.info('Pagination');
    const buttonSelector = 'div.pagination-view-more';

    // Last item date, we have to check it before loop also
    let lastItemsDate = new Date($(".thing-card").last().find('.item-header .item-date').text().replace(/\s/g, ''));

    const weekAgo = new Date(Date.now() - 1000 * 3600 * 24 * 7);

    // We also need to track if we get new items after the click so we dont run in endless loop
    let itemCount = $(".thing-card").length;

    // We only enter the loop if the last item is more recent than week ago
    if (lastItemsDate >= weekAgo) {
        // I chose 'infinite' loop so we can log how we break out
        while (true) {
            log.info('Waiting for the "Show more" button.');
            try {
                await waitFor(buttonSelector);
            } catch (err) {
                // Ignore the timeout error.
                log.info('Could not find the "Show more button", we\'ve reached the end.');
                break;
            }
            log.info('Clicking the "Show more" button.');
            $(buttonSelector).click();
            // Wait a bit so items can load
            await waitFor(5000);

            // Now we check if new items were loaded
            const itemCountAfterClick = $(".thing-card").length;
            if (itemCountAfterClick === itemCount) {
                log.info('No new items, exiting the loop...');
                break;
            }
            itemCount = itemCountAfterClick;

            // Now we check if last item is still within a week. We can compare Dates directly
            lastItemsDate = new Date($(".thing-card").last().find('.item-header .item-date').text().replace(/\s/g, ''));

            if (lastItemsDate < weekAgo) {
                log.info(`Last item date is older than a week, exiting the loop: ${lastItemsDate}`);
                break;
            }
        }
    }

    //export the results
    var result = [];
    $(".thing-card").each(function() {
        result.push({
            title: $(this).attr('title'),
            //format Dec 15, 2019
            date: $(this).find('.item-header .item-date').text().replace(/\s/g, ''),
        });
    });
    return result;

}
于 2020-01-02T07:57:57.137 に答える