【问题标题】:Puppeteer error when using page.evaluate: TypeError: Cannot read property 'innerText' of null使用 page.evaluate 时出现 Puppeteer 错误:TypeError: Cannot read property 'innerText' of null
【发布时间】:2020-09-05 16:43:31
【问题描述】:

enter image description here我是 puppeteer 的新手,我正在尝试从此页面上的表格中抓取数据: https://www.ewrc-results.com/season/1995/wrc-1/.

这是 DOM 中表格的屏幕截图:

我使用的代码如下:

const puppeteer = require('puppeteer');

async function getChampTable(year) {
    try {

        const browser = await puppeteer.launch();

        const page = await browser.newPage();

        const url = `https://www.ewrc-results.com/season/${year}/1-wrc/`;

        await page.goto(url, {waitUntil: 'domcontentloaded'});

        const driverTable = await page.evaluate(() => {
            const grabFromRow = (row, classname) => row
                .querySelector(`td.${classname}`)
                .innerText
                .trim()

            const DRIVER_ROW_SELECTOR = 'tr.table_sude'

            const data = []

            const driverRows = document.querySelectorAll(DRIVER_ROW_SELECTOR)

            for (const tr of driverRows) {
                data.push({
                    position: grabFromRow(tr, 'points-pos'),
                    name: grabFromRow(tr, 'a'),
                    pointsTotal: grabFromRow(tr, 'points-total')
                })
            }
            return data
        })

        console.log(JSON.stringify(driverTable, null, 2))

    } catch (error) {
        console.log(error)
    }
}

getChampTable(1995);

这是我收到的错误:

Error: Evaluation failed: TypeError: Cannot read property 'innerText' of null
    at grabFromRow (__puppeteer_evaluation_script__:4:5)
    at __puppeteer_evaluation_script__:16:12
    at ExecutionContext._evaluateInternal (/Users/jamescowell/Desktop/Projects/Bobble/scraper/node_modules/puppeteer/lib/ExecutionContext.js:102:19)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async ExecutionContext.evaluate (/Users/jamescowell/Desktop/Projects/Bobble/scraper/node_modules/puppeteer/lib/ExecutionContext.js:33:16)
    at async getChampTable (/Users/jamescowell/Desktop/Projects/Bobble/scraper/index.js:14:23)
  -- ASYNC --
    at ExecutionContext.<anonymous> (/Users/jamescowell/Desktop/Projects/Bobble/scraper/node_modules/puppeteer/lib/helper.js:94:19)
    at DOMWorld.evaluate (/Users/jamescowell/Desktop/Projects/Bobble/scraper/node_modules/puppeteer/lib/DOMWorld.js:89:24)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
  -- ASYNC --
    at Frame.<anonymous> (/Users/jamescowell/Desktop/Projects/Bobble/scraper/node_modules/puppeteer/lib/helper.js:94:19)
    at Page.evaluate (/Users/jamescowell/Desktop/Projects/Bobble/scraper/node_modules/puppeteer/lib/Page.js:591:14)
    at Page.<anonymous> (/Users/jamescowell/Desktop/Projects/Bobble/scraper/node_modules/puppeteer/lib/helper.js:95:27)
    at getChampTable (/Users/jamescowell/Desktop/Projects/Bobble/scraper/index.js:14:34)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

任何帮助将不胜感激!

【问题讨论】:

  • 在你的图片中,我没有看到任何td标签,类名是a,这意味着querySelector("td.a")将返回null
  • @hoangdv 感谢您的评论 - 我删除了该行,不幸的是我仍然遇到同样的错误。

标签: javascript node.js dom web-scraping puppeteer


【解决方案1】:

页面的某些表格中有tr.table_sude,但并非所有表格都需要子选择器。您需要使选择器更具体。 (还需要一些更正来提取玩家名称)。

'use strict';

const puppeteer = require('puppeteer');

async function getChampTable(year) {
    try {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        const url = `https://www.ewrc-results.com/season/${year}/1-wrc/`;
        await page.goto(url, {waitUntil: 'domcontentloaded'});

        const driverTable = await page.evaluate(() => {
            const grabFromRow = (row, classname) => row
                .querySelector(classname)
                .innerText
                .trim()

            const DRIVER_ROW_SELECTOR = 'div#points + table tr.table_sude'
            const data = []
            const driverRows = document.querySelectorAll(DRIVER_ROW_SELECTOR)

            for (const tr of driverRows) {
                data.push({
                    position: grabFromRow(tr, 'td.points-pos'),
                    name: grabFromRow(tr, 'a'),
                    pointsTotal: grabFromRow(tr, 'td.points-total')
                })
                console.log(data);
            }
            return data
        })
        console.log(JSON.stringify(driverTable, null, 2))
    } catch (error) {
        console.log(error)
    }
}

getChampTable(1995);

【讨论】:

    猜你喜欢
    • 2018-04-01
    • 1970-01-01
    • 2016-10-28
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 2018-06-30
    • 1970-01-01
    相关资源
    最近更新 更多