You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Phantom提交表单实现网页抓取的技术问询

Scraping UN Population Data (With Form Submissions) Using Node.js + Phantom.js

Alright, let's build out your solution for grabbing data from that UN population statistics page. You mentioned avoiding the official API and going with Node.js + Phantom.js, so here's how to flesh out your existing code snippet and handle form interactions properly.

First, Prep Your Dependencies

Make sure you've installed the required package:

npm install phantom

(Note: Phantom.js is no longer actively maintained, so if you run into issues long-term, consider switching to Puppeteer—we’ll touch on that briefly later.)

Full Working Code Example

Here’s a complete version of your download method with form handling, error catching, and data extraction:

var phantom = require('phantom');
var methods = {};
var loadInProgress = false;
// Fixed the URL (decoded the escaped & for readability)
var url = 'http://data.un.org/Data.aspx?q=population&d=PopDiv&f=variableID:12';

methods.download = async function(req, res) {
    try {
        // Spin up a Phantom.js instance and create a new page
        const instance = await phantom.create();
        const page = await instance.createPage();

        // Track page load state to avoid premature actions
        page.on('onLoadStarted', () => {
            loadInProgress = true;
            console.log('Page started loading...');
        });

        page.on('onLoadFinished', (status) => {
            loadInProgress = false;
            console.log(`Page loaded with status: ${status}`);
        });

        // Open the target page
        const loadStatus = await page.open(url);
        if (loadStatus !== 'success') {
            console.error(`Failed to load page: ${loadStatus}`);
            await instance.exit();
            return res.status(500).send('Failed to load target page');
        }

        // Wait for the form to render (adjust the selector to match the actual form on the site)
        await page.waitForSelector('#aspnetForm', { timeout: 10000 });

        // Example: Fill out a form field (e.g., select a year from a dropdown)
        await page.evaluate(() => {
            // Replace with the actual selector for your target dropdown/input
            const yearDropdown = document.querySelector('#ctl00_cphContent_ddlYear');
            if (yearDropdown) {
                yearDropdown.value = '2023';
                // Trigger a change event if the page relies on it to update
                yearDropdown.dispatchEvent(new Event('change'));
            }
        });

        // Submit the form (again, use the actual submit button selector)
        await page.evaluate(() => {
            const submitBtn = document.querySelector('#ctl00_cphContent_btnSubmit');
            if (submitBtn) submitBtn.click();
        });

        // Wait for the post-submit page load to finish
        await page.waitFor(() => !loadInProgress, { timeout: 15000 });

        // Extract data from the resulting table (adjust selector to match the site's table)
        const populationData = await page.evaluate(() => {
            const dataTable = document.querySelector('#ctl00_cphContent_gdvData');
            if (!dataTable) return null;

            // Convert table rows to a structured array
            return Array.from(dataTable.querySelectorAll('tr')).map(row => {
                return Array.from(row.querySelectorAll('td, th')).map(cell => cell.textContent.trim());
            });
        });

        console.log('Scraped data:', populationData);

        // Clean up the Phantom instance
        await instance.exit();

        // Send the data back if this is an Express endpoint
        res.json({ success: true, data: populationData });
    } catch (error) {
        console.error('Scraping failed:', error);
        res.status(500).send(`Scraping error: ${error.message}`);
    }
};

// If you're using Express, you'd mount this like so:
// app.get('/scrape-un-population', methods.download);

Key Tips for Success

  • Always wait for elements: Use waitForSelector to ensure form fields and data tables are fully rendered before interacting with them—this avoids "element not found" errors from async page loading.
  • Trigger necessary events: Some forms require a change or click event to update the page state, not just setting an input's value.
  • Track load state: The loadInProgress flag ensures you don't try to scrape data before the form submission finishes loading.
  • Adjust selectors: The selectors in the example (like #ctl00_cphContent_ddlYear) are placeholders—use your browser's dev tools to find the actual IDs/classes for form elements on the UN site.

Quick Note on Alternatives

Since Phantom.js is no longer maintained, you might want to consider Puppeteer (Google's official headless Chrome tool) for long-term projects. The core logic (wait for elements, interact with forms, extract data) is nearly identical, but Puppeteer has better documentation and active support.

内容的提问来源于stack exchange,提问作者user3808470

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:53:13