Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > парсинг html с помощью регулярных выражений


Автор: 586 13.7.2008, 07:42
Примерное содержимое html документа:
Код
<a href="11.txt">1111</a>
<a href="22.txt">2222</a>
list
<a href="33.txt">3333</a>
<a href="44.txt">4444</a>
end
<a href="55.txt">5555</a>
<a href="66.txt">6666</a>

Регулярное выражение, которое получает все ссылки из документа:
Код
<a .*?href="(.*?)".*?>(.*?)</a>

Никак не получается модифицировать регулярное выражение, чтобы получить ссылки между словами list и end. Это возможно сделать с помощью одного регулярного выражения, или придётся обрабатывать текст два раза?

Автор: W4FhLF 13.7.2008, 12:46
AFAIK, два раза. Хотя я никогда не юзал мощные движки, вроде тех, что в perl, там скорее всего есть возможность построить такое выражение. 

Автор: 586 13.7.2008, 16:57
А boost::regex и VBScript.RegExp способны обработать подобное выражение?

Автор: W4FhLF 13.7.2008, 17:31
Ну VBScript.RegExp достаточно слабенький, а boost::regex я юзал в рамках базового функционала. Вообще, я даже не представляю как можно было бы составить выражение... Зайди в раздел по PERL и задай там этот вопрос, будет интересно посмотреть как его решат, если что ссылку в личку кинь smile

Автор: corpsehunter 15.7.2008, 15:12
нипонятно, в чем проблема? или я что-то не так понял или все просто - выражение для одной ссылки берешь в скобки и ставишь сзади *, если ссылок может любое количество и добавляешь в регулярное выражение спереди и сзади list и end, соответственно.

Автор: W4FhLF 15.7.2008, 16:43
corpsehunter, я так понял надо получить не весь блок ссылок со словами list и end, а просто ссылки по отдельности, которые находятся в пределах этих слов. 

Автор: corpsehunter 15.7.2008, 23:32
ну дак все равно не вижу проблемы - когда пишешь регулярное выражение с круглыми скобками можно обращаться к отдельно к каждому элементу заключенному в скобки.

Автор: W4FhLF 16.7.2008, 14:34
corpsehunter, ты про какой движок регулярок? В VBScript.RegExp, насколько мне известное, такое невозможно. 

Автор: corpsehunter 18.7.2008, 15:12
в VBScript.RegExp может и нет. давненько уже было - я вообще на яве писал, там было=) Кстати, писал прогу тоже хтмл парсить=)))

Автор: 586 18.7.2008, 20:08
А boost::regex слабый?

Попробовал составить выражение
Код
list(?:.*?<a .*?href="(.*?)".*?>(.*?)</a>.*?)*?end

boost::regex выдал следующее:
Код
[0] = 44.txt
[1] = 4444

а нужно
Код
[0] = 33.txt
[1] = 3333
[2] = 44.txt
[3] = 4444

В чём проблема?
Выложу ещё код (может нужно там флаг какой-нибудь установить?)
Код
#include <windows.h>
#include <locale>
#include <iostream>
#include <string>
#include <vector>
#include <boost/regex.hpp>

const char txt[] = "<a href=\"11.txt\">1111</a>\r\n"
                   "<a href=\"22.txt\">2222</a>\r\n"
                   "list\r\n"
                   "<a href=\"33.txt\">3333</a>\r\n"
                   "<a href=\"44.txt\">4444</a>\r\n"
                   "end\r\n"
                   "<a href=\"55.txt\">5555</a>\r\n"
                   "<a href=\"66.txt\">6666</a>";

void main(int, char**)
{
    setlocale(LC_ALL, "");

    try {
        std::vector<std::string> result;

        if(boost::regex_split(std::back_inserter(result), std::string(txt), 
            boost::regex("list(?:.*?<a .*?href=\"(.*?)\".*?>(.*?)</a>.*?)*?end", boost::regex_constants::icase)))
        {
            std::cout << "Found " << result.size() << " elements" << std::endl;
            for(UINT i = 0; i < result.size(); ++i)
            {
                std::cout << "[" << i << "] = " << result[i] << std::endl;
            }
        } else {
            std::cout << "Not found" << std::endl;
        }
    }
    catch(std::exception &ex) {
        std::cout << "EXCEPTION: " << ex.what() << std::endl;
    }

    std::cin.get();
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)