1

Тема: WSH: Парсинг HTML

Всем доброго времени суток!

Хочу найти удобное решение для парсинга HTML. Не в контексте определенной задачи, а, скорее, общий подход, позволяющий по заложенному принципу извлечь данные из HTML кода, полученного с помощью HTTP-запроса. Например, извлечь текстовое содержимое элементов с определенными аттрибутами или / и расположением в дереве: ячеек в столбце таблицы, пунктов выпадающего списка; получить значения скрытых полей формы для POST-запроса, и т. п.. Определяющие критерии - быстрая и гибкая настройка и подбор шаблонов под структуру конкретного сайта, без установки / регистрации дополнительных компонентов.

Первое, что приходит в голову - работа с DOM, вероятно даже подключение функционала jQuery. Но хотелось бы отказаться от использования IE и htmlfile, таким образом предотвратив запуск скриптов, активного содержимого (java-плагинов, flash, ...), загрузку внешних ресурсов (изображений, медиа-файлов, скриптов, CSS, ...). Так же популярны RegExp и XPath. На мой взгляд для подобных задач лучшей будет реализация на MSXML с XPath, но тут актуален вопрос преобразования HTML в валидный XML.

Поделитесь решениями, которые приходилось использовать вам.

Вот некоторые ссылки, относящиеся к вопросу:
AutoIt3: Парсер HTML
VBS: Парсинг HTML через MSXML
JScript: Эмуляция браузера
Pure JavaScript HTML Parser
XML Syntax Rules
Примеры xpath-запросов к html

Щт Уккщк Куыгьу Туче
’ҐЄгй п Є®¤®ў п бва Ёж : 1251

2

Re: WSH: Парсинг HTML



HTMLParse("<script>alert()</script>");
HTMLParse("<script>alert()</script>",1);

function HTMLParse(code, dont_prevent_code_exec)
{
    var document = new ActiveXObject("HTMLFile");
    if (!dont_prevent_code_exec) document.designMode = 'on';
    document.write(code);
    document.close();
    if (!dont_prevent_code_exec) document.execCommand('stop');
    return document.parentWindow;
}

jQuery лень переделывать под WSH .


Что касается конвертирования, то вполне можно проходить по дереву узлов и структуре атрибутов. А если заниматься поиском и заменой, то возможны ошибки.

3 (изменено: wisgest, 2015-07-15 00:10:49)

Re: WSH: Парсинг HTML

Когда передо мной встала такая задача, в HTA я воспользовался созданным с помощью document.createElement() элементом BODY, установив его содержимое через .innerHTML. Пока такой элемент не вставлен в документ, можно работать с деревом его узлов, но внешние ресурсы не загружаются и активное содержимое не выполняется. Думаю, вместо BODY с таким же успехом можно было использовать DIV, но ни элемент HTML, ни HEAD подобным образом использовать нельзя.

Element = document.createElement("BODY");
Element.innerHTML = Request.responseText;

Table = Element.getElementsByTagName("TABLE").item(3);
count = Table.rows.length;
// . . .

При этом за бортом оказывается всё содержимое HEAD, а также элементы TITLE и META, даже если они находятся в BODY. Чтобы не терялись находящиеся в HEAD элементы BASE, LINK, STYLE, SCRIPT можно добавить "<body>" в начало текста загружаемого в .innerHTML (или какой нибудь знак недопустимый в HEAD, например, "&nbsp;").

Не в HTA можно поступить подобным же образом:

htmldoc = new ActiveXObject("htmlfile");
htmldoc.write(""); htmldoc.close();
Element = htmldoc.createElement("BODY");
Element.innerHTML = "HTML-код для разбора";

но можно и проще:

htmldoc = new ActiveXObject("htmlfile");
htmldoc.write(""); htmldoc.close();
htmldoc.body.innerHTML = "HTML-код для разбора";

— похоже, что так тоже внешние ресурсы не загружаются и активное содержимое не выполняется, но не уверен, что это не зависит ни от каких, возможно, нигде не описанных настроек. При этом, правда, упрощается разбор таблиц стилей из элементов STYLE:

+ code
HTML = "<style type='text/css'>img {width: 200px;}</style>";
htmldoc = new ActiveXObject("htmlfile");
htmldoc.write(""); htmldoc.close();
htmldoc.body.innerHTML = "<body>" + HTML;
css = htmldoc.styleSheets.item(0);
WScript.Echo(css.cssText);

но не намного

+ code
HTML = "<style type='text/css'>img {width: 200px;}</style>";
htmldoc = new ActiveXObject("htmlfile");
htmldoc.write(""); htmldoc.close();
element = htmldoc.createElement("body");
element.innerHTML = "<body>" + HTML;
css = htmldoc.createStyleSheet();
css.cssText = element.getElementsByTagName("style").item(0).innerHTML;
WScript.Echo(
    css.rules.item(0).selectorText + " {"
    + css.rules.item(0).style.cssText + "}");

4

Re: WSH: Парсинг HTML

wisgest, мы с коллегой JSman, когда обсуждали эту тему, пришли к выводу, что вариант с document.write всё же предпочтительнее чем вставка в innerHTML. Выполнение скриптов можно предотвратить переводом документа в designMode, а корректность обработки стилей и прочих плюшек выполняется правильнее. А строку document.execCommand('stop') я пока что убрал из своего кода, так как с последними апдейтами на Win 7 проблема с подгрузкой ActiveX в документе пропала. В остальном код получается более компактным, имхо.

var XMLHTTP = new ActiveXObject("Msxml2.XMLHTTP")

XMLHTTP.open('GET','http://rating.rbc.ru/',false)
XMLHTTP.send()

var doc = parseHTML(XMLHTTP.responseText)

WScript.Echo(doc.styleSheets[0].cssText)

function parseHTML(text){
    var doc = new ActiveXObject("htmlfile")
    doc.designMode = 'on';
    doc.write(text);
    doc.close();
    return doc
}
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !