Выполнение JavaScript кода во время парсинга

Выполнение JavaScript кода во время парсинга

Очень часто во время парсинга сайтов возникает проблема вычисления различных данных нужных, например, для запроса следующей страницы. Ситуаций, где потребуются дополнительные вычисления, может быть очень много, но большая часть из них может быть решена с помощью команды eval.

Для примера представим что нам нужно получить текущее время в формате unix-time(%s) и добавить его к какому-то линку что бы сделать запрос.
Эта проблема решается несколькими способами:

Способ 1

Сохраним линк в переменную, выполним eval и соединим значения, обратите внимание что если вам нужно вернуть значение в регистр ваша функция должна быть обернута в замыкание и иметь return в конце выполнения.

    ...
    ...
    - find:
        path: a
        do:
        - parse:
            attr: href
        - variable_set: link
        - eval:
            routine: js
            body: "(function (){return new Date().getTime();})();"
        - variable_prepend:
            field: link
            joinby: "?time="
        # в регистре будет находиться http://somelink.com/?time=1476403635606
        - walk:
            to: value
            do:
            ...
            ...
                        ...

Способ 2

Второй способ это записать значение из js функции в переменную. Для этого используется подкоманда assign.

    ...
    ...
    - find:
        path: a
        do:
        - parse:
            attr: href
        - eval:
            routine: js
            body: "var jstime = new Date().getTime();"
            assign:
                time: jstime
        - variable_append:
            field: time
            joinby: "?time="
        # в регистре будет находиться http://somelink.com/?time=1476403635606
        - walk:
            to: value
            do:
            ...
            ...
            ...

Способ 3

Или мы можем передать переменную в javascript код, и вернуть нужное нам значение сразу.

    ...
    ...
    - find:
        path: a
        do:
        - parse:
            attr: href
        - variable_set: link
        - eval:
            routine: js
            body: "(function (){return '<%link%>' + '?time=' + new Date().getTime();})();"
        # в регистре будет находиться http://somelink.com/?time=1476403635606
        - walk:
            to: value
            do:
            ...
            ...
            ...

Обратите внимание что все переменные должны быть обёрнуты в кавычки, т.к являются строковыми.

Можно писать более сложные функции, так же можно выполнять функции которые находятся на странице в тегах скрипт, но вы должны помнить что функции не работают с DOM и функции не должны выполняться длительное время.

В противном случае вы увидите что-то вроде этого:

{"level":"error","msg":"Eval error: RangeError: Maximum call stack size exceeded","time":"2016-10-14T06:12:12.2624413+03:00"}
{"level":"error","msg":"Eval error: Code execution time exceeded limits. Stopping after: 10.0004sec","time":"2016-10-14T06:16:22.9742751+03:00"}