Ошибка выдачи Jsdom для некоторых URL-адресов

Я новичок в nodejs, я пытаюсь сканировать все URL-адреса моего сайта (с включенными javascript и jquery) и проверять, содержит ли URL-адрес заданную строку.

Для этого я использую jsdom, но когда я запускаю скрипт извлекает только некоторые URL-адреса, а затем вылетает, выдавая эту ошибку:

timers.js:110
    first._onTimeout();
          ^
TypeError: Property '_onTimeout' of object [object Object] is not a function
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

Наверняка что-то не так, но я не понимаю где..

Это мой сценарий:

var request = require('request');
var jsdom = require('jsdom');

request({ uri: 'http://www.example.com' }, function (error, response, html) {
  if (!error && response.statusCode == 200) {

     var doc = jsdom.jsdom(html, null, {
           features: {
              FetchExternalResources   : ['script'],
              ProcessExternalResources : ['script'],
              MutationEvents           : '2.0',
           }
     });

     var window = doc.createWindow();
     jsdom.jQueryify(window, "http://code.jquery.com/jquery-1.5.min.js", function() {
        var $ = window.jQuery;
        $('a').each(function(i, element){
             var a = $(this).attr('href');
             console.log(a);
             if (a.indexOf('string') != -1) {
               console.log('The winner: '+a);
               //return a;
             }
        });
        window.close();
    });
  }
});

person Lughino    schedule 17.12.2013    source источник
comment
У меня такая же проблема, но только на некоторых URL. Я еще не определил, является ли это ошибкой, вызванной фактическим выполнением скриптов в очищенном html, или это внутренняя ошибка в коде jsdom. Знаки указывают на оба прямо сейчас :)   -  person Anders Bornholm    schedule 07.02.2014
comment
Я сделал запрос на вытягивание по совету @faridNouriNeshat: github.com/tmpvar/jsdom/pull /1186   -  person Ashley Coolman    schedule 08.08.2015


Ответы (1)


Это связано с тем, что где-то на вашей странице они вызывают setTimeout/setInterval со строкой, которая не поддерживается в узле, и это приводит к этой ошибке.

Чтобы узнать, откуда он берется, я предлагаю просто запросить модуль longjohn (require('longjohn')), и вы получите лонг трассировки стека, которые помогут вам найти ошибку. Например, я получил что-то подобное, сделав это в repl:

    at listOnTimeout (timers.js:110:15)
---------------------------------------------
    at startTimer (/home/alfred/repos/node_modules/jsdom/lib/jsdom/browser/index.js:75:15)
    at DOMWindow.setTimeout (/home/alfred/repos/node_modules/jsdom/lib/jsdom/browser/index.js:124:50)
    at file:///home/alfred/repos/repl:undefined:undefined<script>:1:1
    at Contextify.sandbox.run (/home/alfred/repos/node_modules/jsdom/node_modules/contextify/lib/contextify.js:12:24)
    at exports.javascript (/home/alfred/repos/node_modules/jsdom/lib/jsdom/level2/languages/javascript.js:5:14)
    at define.proto._eval (/home/alfred/repos/node_modules/jsdom/lib/jsdom/level2/html.js:1523:47)
    at /home/alfred/repos/node_modules/jsdom/lib/jsdom/level2/html.js:76:20
    at item.check (/home/alfred/repos/node_modules/jsdom/lib/jsdom/level2/html.js:345:11)

Если вдруг у вас это не сработало или вам не понравилось, то я предлагаю вам изменить этот файл jsdom: node_modules/jsdom/lib/jsdom/browser/index.js, функция startTimer. Сбросьте туда ошибку, если callback не была функцией. Это будет срабатывать всякий раз, когда запускается оскорбительный код.

В случае, если вы используете код, который вы не можете изменить (например, с веб-сайтов, которыми вы не владеете, что я не предлагаю, потому что такой иностранный javascript может использоваться для атаки на ваше приложение), вы можете переопределить DOMWindow.setTimeout /.setInterval для поддержки строковых аргументов. Вы также можете открыть проблему для jsdom, чтобы иметь эту возможность.

person Farid Nouri Neshat    schedule 06.04.2014