void AddTextBlocks(int page_id, CString html) {
//Объявляем MSHTML переменные и создаём документ
MSHTML::IHTMLDocument2Ptr pDoc;
MSHTML::IHTMLDocument3Ptr pDoc3;
MSHTML::IHTMLElementCollectionPtr pCollection;
MSHTML::IHTMLElementPtr pElement;
HRESULT hr = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER,
IID_IHTMLDocument2, (void**)&pDoc);
//заносим код в SAFEARRAY и записываем его в документ
SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
VARIANT *param;
bstr_t bsData = (LPCTSTR)html;
hr = SafeArrayAccessData(psa, (LPVOID*)¶m);
param->vt = VT_BSTR;
param->bstrVal = (BSTR)bsData;
hr = pDoc->write(psa);
hr = pDoc->close();
bsData.Detach();
SafeArrayDestroy(psa);
//использую IHTMLDocument3 для получения тегов.
//эта функция доступна только в IE5 +
//есть вариант без использования IHTMLDocument3 - можно просто запустить через все теги HTML
// (IHTMLDocument2->all)
pDoc3 = pDoc;
//список тэгов для обработки
vector<CString> tags_names = GetListsOfContentTag();
for (int i = 0; i < tags_names.size(); i++) {
pCollection = pDoc3->getElementsByTagName(bstr_t(tags_names));
for(long j = 0; j < pCollection->length; j++){
pElement = pCollection->item(j, (long)0);
if(pElement != NULL){
//второй параметр означает, что необходимо получить текст внутри атрибута
//CString str = pElement->getAttribute("href", 2);
//получаем содержимое тэга
CString text = (LPCTSTR)pElement->GetinnerText();
}
}
}
//добавляем информацию о текстовых блоках в БД
AddTextBlocksToDb(blocks);
}
HTML Parser
Необходимо написать parser содержимого html - в частности, тэгов
Лично я в основу положил обычный проход по html, с поиском начального символа тэга <, определения типа тэга и считывания его содержимого до следующего открывающего, либо закрывающего тэга
Плюс, необходимо учитывать вложенность тэгов
То есть, если ситуация
[HTML]<div>текст1 <a>текст2</a> текст3</div>[/HTML]
то в результате должно получиться
div : текст 1 текст2 текст3
div, a : текст 2
a сохраняется, так как у него тип - inside (сам придумал), тк, если не приписывать содержимое тэга а в тэг div, может потеряться смысл содержимого тэга div
Вобщем-то, алгоритм почти реализован, но ситуация с вложенностью в нём обрабатывается плохо...
Может, у кого-то будут какие-то свежие идеи на счёт такого parser'а html?
Буду благодарен за любой ответ!
Ежели не пользуетесь .NET'ом - почему не регулярки? Последовательно ищете в документе все конструкции вида <tag>bla-bla-bla</tag>, потом проходитесь рекурсивно по bla-bla-bla и строите дерево.
Цитата: Alexander92
А что, стандартный XMLDocument и иже с ним не оно? На чем вообще пишете?
Ежели не пользуетесь .NET'ом - почему не регулярки? Последовательно ищете в документе все конструкции вида <tag>bla-bla-bla</tag>, потом проходитесь рекурсивно по bla-bla-bla и строите дерево.
Ежели не пользуетесь .NET'ом - почему не регулярки? Последовательно ищете в документе все конструкции вида <tag>bla-bla-bla</tag>, потом проходитесь рекурсивно по bla-bla-bla и строите дерево.
пишу на MFC
думал по поводу рекурсии, но это ведь, по идее, медленнее, чем однопроходный алгоритм
но по факту вышло, что однопроходный не даёт достоверного хотя бы 90% результата
по поводу XMLDocument...если честно, в C++ ни разу не использовал, а там есть возможности для такого парсинга?
регулярки в C++ тоже не использовал, мне писали сюда код...
Вообще, регулярки в MFC, C++ через #include <atlrx.h> использовать надо?
Я вот пробовал, у меня этот заголовок не находился
Можешь примерно описать, в какую сторону можно копнуть?
XMLDocument - это из .NET, в MFC ты этим не воспользуешься. Только если полезешь в управляемый код.
По поводу "куда копнуть" - либо строй конечный автомат и делай однопроходный алгоритм, либо рекурсивно. А потом можно будет сравнить, что быстрее и эффективнее. Подобные конечные автоматы почти в любой соответствующей литературе описаны, посмотри.
Цитата: Alexander92
Да можно и однопроходным, в общем-то;
Порты SAX-а вроде и на C/C++ есть.
Цитата: Freeman
Порты SAX-а
а что это такое?
MSXML и не занимаемся ерундой.
Юзаем
Спасибо за совет!
Но можешь хотя бы вкратце натолкнуть на то, октуда копать в этом направлении?
В гугле я разъясняющей информации не нашёл
потому что, например, для load метода сказано:
Цитата:
load Method
Loads an XML document from the specified location.
Loads an XML document from the specified location.
Зато алгоритм сразу становится проще и нагляднее. Некоторые вещи весьма геморно реализовывать без рекурсии и если она нужна, то непременно надо её использовать. Тут как раз такой случай.
Например может быть такое:
<a href=/dir/>ссылка</a> - это нужно понимать как href="/dir/", а не как <a href="/dir" />
Часто встречаются непарные теги, иногда попадаются спецсимволы "<" и ">", не являющиеся началом или концом тега.
Один раз я видел лишний тег <body> в середине страницы и без соответствующего закрывающего.
Браузеры это умеют распознавать и отображают страницы нормально, но самостоятельно перебрать все возможные извращения будет сложно.
Вобщем-то, это уже реализовано
Вот код:
Он выполняет сканирование содержимого тэгов, заданных в списке
Код:
Всем спасибо за советы :)