【问题标题】:How do I scrape data in <canvas> element with python or javascript?如何使用 python 或 javascript 抓取 <canvas> 元素中的数据?
【发布时间】:2020-04-23 05:18:54
【问题描述】:

我想从像 this (stat game of the game I play) 这样的网站中抓取数据,其中交互式图表在 &lt;canvas&gt; 元素中呈现,并且不将任何数据显示为可抓取的 HTML 元素。 检查 HTML,页面似乎使用chartjs

虽然python中的帮助是首选,但如果我真的需要使用一些javascript,那也很好。

另外,我想避免使用需要额外文件的方法,例如 phantomjs,但同样,如果这是唯一的方法,请慷慨地分享它。

【问题讨论】:

  • 对于 python 你可以使用 selenium
  • 可以分享一下页面的网址吗?
  • @IainShelvington 我不知道如何使用硒从画布上抓取数据。我是网页抓取的菜鸟;;;
  • 你不能刮canvas,因为它像图像,所以你需要使用一些软件来识别图像,但是你可以在你的页面上找到canvas里面的所有数据,例如在这个标签//div [@class='playerStatPage']/following-sibling::script 或在图像元素中,例如 //div[@id='ribbons-sm']/div[@class='ribbon-wrapper']跨度>
  • 你不需要javascript

标签: javascript python python-3.x web-scraping chart.js


【解决方案1】:

解决此问题的一种方法是检查页面源中第 1050 行附近页面的 &lt;script&gt;,这实际上是图表初始化的位置。在图表的初始化过程中有一个循环模式,其中画布元素被逐个查询以获取它们的上下文,然后是提供图表标签和统计信息的变量。

此解决方案涵盖使用 node.js,至少包含以下模块的最新版本:

  • cheerio 用于查询 DOM 中的元素
  • axios 发送http请求获取页面源。
  • abstract-syntax-tree 获取我们希望抓取的脚本的 javascript 对象树表示。

这是solution 和下面的源代码:

const cheerio = require('cheerio');

const axios = require('axios');

const { parse, each, find } = require('abstract-syntax-tree');

async function main() {

    // get the page source
    const { data } = await axios.get(
        'https://stats.warbrokers.io/players/i/5d2ead35d142affb05757778'
    );

    // load the page source with cheerio to query the elements
    const $ = cheerio.load(data);

    // get the script tag that contains the string 'Chart.defaults'
    const contents = $('script')
        .toArray()
        .map(script => $(script).html())
        .find(contents => contents.includes('Chart.defaults'));

    // convert the script content to an AST
    const ast = parse(contents);

    // we'll put all declarations in this object
    const declarations = {};

    // current key
    let key = null;

    // iterate over all variable declarations inside a script
    each(ast, 'VariableDeclaration', node => {

        // iterate over possible declarations, e.g. comma separated
        node.declarations.forEach(item => {

            // let's get the key to contain the values of the statistics and their labels
            // we'll use the ID of the canvas itself in this case..
            if(item.id.name === 'ctx') { // is this a canvas context variable?
                // get the only string literal that is not '2d'
                const literal = find(item, 'Literal').find(v => v.value !== '2d');
                if(literal) { // do we have non- '2d' string literals?
                    // then assign it as the current key
                    key = literal.value;
                }
            }

            // ensure that the variable we're getting is an array expression
            if(key && item.init && item.init.type === 'ArrayExpression') {

                // get the array expression
                const array = item.init.elements.map(v => v.value);

                // did we get the values from the statistics?
                if(declarations[key]) {

                    // zip the objects to associate keys and values properly
                    const result = {};
                    for(let index = 0; index < array.length; index++) {
                        result[array[index]] = declarations[key][index];
                    }
                    declarations[key] = result;

                    // let's make the key null again to avoid getting
                    // unnecessary array expression
                    key = null;

                } else {
                    // store the values
                    declarations[key] = array;
                }
            }

        });

    });

    // logging it here, it's up to you how you deal with the data itself
    console.log(declarations);

}

main();

【讨论】:

  • 我喜欢你聪明的反应。这是python还是Javascript?无论哪一个,你都可以做一步一步的教程视频。我正在从事类似的项目,但遇到了问题。 @ryeballar
猜你喜欢
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-20
  • 1970-01-01
  • 2018-04-04
相关资源
最近更新 更多