Выбрать url из страницы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 06.10.07 06:16
Оценка:
Добрый день!
Пытаюсь выбрать урл из html кода.
Вопрос мой скорее к знатокам регулярных выражений.
Написал вот я код на С++


    string m_s = "dsfdsfd fsdf <a href = \"http://google.com?text=\"    />hello</a> ewf ewf ";
    boost::regex expression("<\\s*a\\s*href\\s*=\\s*(?>[\\\"\\\'])?([^\\s\\>\\\'\\\"]+)(?>[\\\"\\\'])?.*>",boost::regbase::normal);
    std::string::const_iterator start = m_s.begin(), end = m_s.end();
    boost::match_results<std::string::const_iterator> what;
    boost::match_flag_type flags = boost::match_default;

    while( boost::regex_search(start, end, what, expression, flags) ){

        string url = what[1];
        start = what[0].second;
    }


и собственно регулярка, ее нашел на каком то сайте.

<\\s*a\\s*href\\s*=\\s*(?>[\\\"\\\'])?([^\\s\\>\\\'\\\"]+)(?>[\\\"\\\'])?.*>

Но проблема в том что регулярное выражение это не может выбрать правильно скажем такие урл
<a href="http://google.com?id='10'">
<a href='http://google.com"> — не правильно!

я понимаю что выражение (?>[\\\"\\\'])? — должен встретится символ ' или " или вообще ни один из них

А как сделать, чтобы скажем результат (?>[\\\"\\\'])? запомнился и применился после окончания урл? т.е.
если стоит " в начале, то и заканчиватся урл должен только "
http://www.samborsky.com — мой блог
Re: Выбрать url из страницы
От: Yagg Россия  
Дата: 06.10.07 08:32
Оценка:
Здравствуйте, Socket, Вы писали:

S>А как сделать, чтобы скажем результат (?>[\\\"\\\'])? запомнился и применился после окончания урл? т.е.

S>если стоит " в начале, то и заканчиватся урл должен только "

Использовать back references.
<\\s*a\\s+href\\s*=\\s*(?>[\\\"\\\'])?([^\\s\\>\\\'\\\"]+)\\1.*>
Re: Выбрать url из страницы
От: Roman Odaisky Украина  
Дата: 06.10.07 10:08
Оценка:
Здравствуйте, Socket, Вы писали:

S><\\s*a\\s*href\\s*=\\s*(?>[\\\"\\\'])?([^\\s\\>\\\'\\\"]+)(?>[\\\"\\\'])?.*>


Неправильное оно: <A CLASS=LARGE HREF="http://example.com">.

Возьми лучше парсер HTML. Или просто парсер, которому можно задавать грамматику. Что-то вроде:
tag ::= '<' alnum+ (whitespace attribute)* '>'
attribute ::= alnum+ ('=' string)?
string ::=
    '\'' <anything except '\'' and '>'>* '\'' |
    '"'  <anything except '"' and '>'>*  '"' |
    <anything except whitespace>

Некрасиво, но имеет шанс работать.

И еще: в XHTML все теги и атрибуты требуют нижнего регистра, в HTML это необязательно.
До последнего не верил в пирамиду Лебедева.
Re[2]: Выбрать url из страницы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 06.10.07 16:43
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, Socket, Вы писали:


S>><\\s*a\\s*href\\s*=\\s*(?>[\\\"\\\'])?([^\\s\\>\\\'\\\"]+)(?>[\\\"\\\'])?.*>


RO>Неправильное оно: <A CLASS=LARGE HREF="http://example.com">.


Я забыл указать что html код изначально прирявнян к нижнему регистру, потому icase флаг мне не нужен.
http://www.samborsky.com — мой блог
Re[2]: Выбрать url из страницы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 06.10.07 16:56
Оценка:
Здравствуйте, Yagg, Вы писали:

Y>Здравствуйте, Socket, Вы писали:


S>>А как сделать, чтобы скажем результат (?>[\\\"\\\'])? запомнился и применился после окончания урл? т.е.

S>>если стоит " в начале, то и заканчиватся урл должен только "

Y>Использовать back references.
Y><\\s*a\\s+href\\s*=\\s*(?>[\\\"\\\'])?([^\\s\\>\\\'\\\"]+)\\1.*>


Почему то ругулярка которую вы мне дали не работает.
Может быть я чтото не так делаю?

т.к. вы мне дали линк на описание синтаксиса перла, то я добавил boost::regex::perl
    string m_s = "dsfdsfd<a href='/frame/index.aspx'/>Russ fsdf <a src = \"123\"    />hello</a> ewf <a href='/frame/index.aspx'>Russewf ";
    boost::regex expression("<\\s*a\\s+href\\s*=\\s*(?>[\\\"\\\'])?([.*]+)\\1.*>",boost::regex::perl);
    std::string::const_iterator start = m_s.begin(), end = m_s.end();
    boost::match_results<std::string::const_iterator> what;
    boost::match_flag_type flags = boost::match_default;

    while( boost::regex_search(start, end, what, expression, flags) ){

        string s = what[0];
        string url = what[1];

        start = what[0].second;
    }
http://www.samborsky.com — мой блог
Re: Выбрать url из страницы
От: c-smile Канада http://terrainformatica.com
Дата: 06.10.07 17:34
Оценка:
Здравствуйте, Socket, Вы писали:

S>Добрый день!

S>Пытаюсь выбрать урл из html кода.
S>Вопрос мой скорее к знатокам регулярных выражений.
S>Написал вот я код на С++

...

Берем:
http://www.codeproject.com/cpp/HTML_XML_Scanner.asp

и пишем:

int main(int argc, char* argv[])
{
  str_istream si("<html><body><a href=# >Hello world</a></body></html>");
  markup::scanner sc(si);
  bool in_text = false;
  while(true)
  {
    int t = sc.get_token();
    if( t ==  markup::scanner::TT_EOF )
      break; 
    if( t == markup::scanner::TT_ATTR )
    {
      if( strcmp( sc.get_attr_name(), "href" ) == 0 )
          printf("\tlink to:%S\n", sc.get_value()); // печатаем линк.
    }
  }
FINISH:
  return 0;
}


Ссыоки на внешние источники — это атрибут href.
Есть еще src — адреса внешних ресурсов.


Просто regexp напускать на html нельзя ибо ты найдешь все на свете. например:
<p>http://test.com</p>
Re[2]: Выбрать url из страницы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 06.10.07 17:52
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, Socket, Вы писали:


S>>Добрый день!

S>>Пытаюсь выбрать урл из html кода.
S>>Вопрос мой скорее к знатокам регулярных выражений.
S>>Написал вот я код на С++

CS>...


CS>Берем:

CS>http://www.codeproject.com/cpp/HTML_XML_Scanner.asp

а по скорости он как? быстро работает?
http://www.samborsky.com — мой блог
Re[2]: Выбрать url из страницы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 06.10.07 19:09
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, Socket, Вы писали:


S>>Добрый день!

S>>Пытаюсь выбрать урл из html кода.
S>>Вопрос мой скорее к знатокам регулярных выражений.
S>>Написал вот я код на С++

CS>...


CS>Берем:

CS>http://www.codeproject.com/cpp/HTML_XML_Scanner.asp

CS>и пишем:


CS>
CS>int main(int argc, char* argv[])
CS>{
CS>  str_istream si("<html><body><a href=# >Hello world</a></body></html>");
CS>  markup::scanner sc(si);
CS>  bool in_text = false;
CS>  while(true)
CS>  {
CS>    int t = sc.get_token();
CS>    if( t ==  markup::scanner::TT_EOF )
CS>      break; 
CS>    if( t == markup::scanner::TT_ATTR )
CS>    {
CS>      if( strcmp( sc.get_attr_name(), "href" ) == 0 )
CS>          printf("\tlink to:%S\n", sc.get_value()); // печатаем линк.
CS>    }
CS>  }
CS>FINISH:
CS>  return 0;
CS>}

CS>


CS>Ссыоки на внешние источники — это атрибут href.

CS>Есть еще src — адреса внешних ресурсов.


CS>Просто regexp напускать на html нельзя ибо ты найдешь все на свете. например:

CS><p>http://test.com</p>


попробовал эту библиотеку, не справляется с такими данными


    str_istream si("<html><body><a href=rsdn.ru/index.php>world</a>");


печатает rsdn.ru, а должен до пробела или окончания тега rsdn.ru/index.php

    str_istream si("<html><body><a href=http://rsdn.ru/index.php>world</a>");


печатает http, а должен до пробела или окончания тега http://rsdn.ru/index.php
http://www.samborsky.com — мой блог
Re[3]: Выбрать url из страницы
От: c-smile Канада http://terrainformatica.com
Дата: 06.10.07 20:20
Оценка: 3 (1)
Здравствуйте, Socket, Вы писали:

S>попробовал эту библиотеку, не справляется с такими данными



S>
S>    str_istream si("<html><body><a href=rsdn.ru/index.php>world</a>");
S>


S>печатает rsdn.ru, а должен до пробела или окончания тега rsdn.ru/index.php


S>
S>    str_istream si("<html><body><a href=http://rsdn.ru/index.php>world</a>");
S>


S>печатает http, а должен до пробела или окончания тега http://rsdn.ru/index.php


В файле xh_scanner.cpp поменяй:

      else  // scan token, allowed in html: e.g. align=center
        do
        {
            if( is_whitespace(c) ) return TT_ATTR;
            if( c == '/' || c == '>' ) { push_back(c); return TT_ATTR; }
            if( c == '&' ) c = scan_entity();
            append_value(c);
        } while(c = get_char());


на

      else  // scan token, allowed in html: e.g. align=center
        do
        {
            if( is_whitespace(c) ) return TT_ATTR;
            if( c == '>' ) { push_back(c); return TT_ATTR; }
            append_value(c);
        } while(c = get_char());


и будет тебе шастя.
Re[4]: Выбрать url из страницы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 06.10.07 21:25
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>и будет тебе шастя.


Действительно щастья подвалило с твоим исправлением.
На долго ли — отпишу ч-з пару дней, поюзаем эту либу на скорость и вылеты, я отпишу насколько она хороша
http://www.samborsky.com — мой блог
Re[2]: Выбрать url из страницы
От: __SPIRIT__ Россия  
Дата: 16.10.07 11:32
Оценка:
Здравствуйте, c-smile,

Этот код можно использовать в коммерческом проекте?
... << RSDN@Home 1.2.0 alpha rev. 746>>
Re[5]: Выбрать url из страницы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 16.10.07 11:43
Оценка:
Здравствуйте, Socket, Вы писали:

S>Здравствуйте, c-smile, Вы писали:


CS>>и будет тебе шастя.


S>Действительно щастья подвалило с твоим исправлением.

S>На долго ли — отпишу ч-з пару дней, поюзаем эту либу на скорость и вылеты, я отпишу насколько она хороша

Общал отписать отзыв о этой библиотеке.
В общем неделю работает. Работает быстро, вылетов из за использования этой библиотеки не было обнаружено.
В общем буду продалжать использовать ее для выбора урл
http://www.samborsky.com — мой блог
Re[3]: Выбрать url из страницы
От: c-smile Канада http://terrainformatica.com
Дата: 18.10.07 02:49
Оценка:
Здравствуйте, __SPIRIT__, Вы писали:

__S>Здравствуйте, c-smile,


__S>Этот код можно использовать в коммерческом проекте?


Да
Re[4]: Выбрать url из страницы
От: __SPIRIT__ Россия  
Дата: 19.10.07 13:40
Оценка:
Здравствуйте, c-smile, Вы писали:

Не работает для

 str_istream si(
    "<a href='http://terrainformatica.com/index.php?a=1&b=2'>link</a>");
... << RSDN@Home 1.2.0 alpha rev. 746>>
Re[5]: Выбрать url из страницы
От: Socket Ниоткуда http://www.samborsky.com
Дата: 19.10.07 14:42
Оценка: 30 (1)
Здравствуйте, __SPIRIT__, Вы писали:

__S>Здравствуйте, c-smile, Вы писали:


__S>Не работает для


__S>
__S> str_istream si(
__S>    "<a href='http://terrainformatica.com/index.php?a=1&b=2'>link</a>");
__S>


Похоже что нужно сделать так:


    scanner::token_type scanner::scan_head()
    {
      wchar c = skip_whitespace();

      if(c == '>') { c_scan = &scanner::scan_body; return scan_body(); }
      if(c == '/')
      {
         wchar t = get_char();
         if(t == '>')   { c_scan = &scanner::scan_body; return TT_TAG_END; }
         else { push_back(t); return TT_ERROR; } // erroneous situtation - standalone '/'
      }

      attr_name_length = 0;
      value_length = 0;

      // attribute name...
      while(c != '=') 
      {
        if( c == 0) return TT_EOF;
        if( c == '>' ) { push_back(c); return TT_ATTR; } // attribute without value (HTML style)
        if( is_whitespace(c) )
        {
          c = skip_whitespace();
          if(c != '=') { push_back(c); return TT_ATTR; } // attribute without value (HTML style)
          else break;
        }
        if( c == '<') return TT_ERROR;
        append_attr_name(c);
        c = get_char();
      }

      c = skip_whitespace();
      // attribute value...
      
      if(c == '\"')
        while(c = get_char())
        {
            if(c == '\"') return TT_ATTR;
            //if(c == '&') c = scan_entity();
            append_value(c);
        }
      else if(c == '\'') // allowed in html
        while(c = get_char())
        {
            if(c == '\'') return TT_ATTR;
            //if(c == '&') c = scan_entity();
            append_value(c);
        }
      else  // scan token, allowed in html: e.g. align=center
          do
          {
              if( is_whitespace(c) ) return TT_ATTR;
              if( c == '>' ) { push_back(c); return TT_ATTR; }
              append_value(c);
          } while(c = get_char());

      return TT_ERROR;
    }


Но хочется конечно услышать мнение автора Fast and Compact HTML/XML Scanner/Tokenizer c_smile
http://www.samborsky.com — мой блог
Re[6]: Выбрать url из страницы
От: c-smile Канада http://terrainformatica.com
Дата: 19.10.07 16:00
Оценка:
Здравствуйте, Socket, Вы писали:

S>Здравствуйте, __SPIRIT__, Вы писали:


__S>>Здравствуйте, c-smile, Вы писали:


__S>>Не работает для


__S>>
__S>> str_istream si(
__S>>    "<a href='http://terrainformatica.com/index.php?a=1&b=2'>link</a>");
__S>>


S>Похоже что нужно сделать так:



S>
S>    scanner::token_type scanner::scan_head()
S>    {
...
S>      if(c == '\"')
S>        while(c = get_char())
S>        {
S>            if(c == '\"') return TT_ATTR;
S>            //if(c == '&') c = scan_entity();
S>            append_value(c);
S>        }
S>      else if(c == '\'') // allowed in html
S>        while(c = get_char())
S>        {
S>            if(c == '\'') return TT_ATTR;
S>            //if(c == '&') c = scan_entity();
S>            append_value(c);
S>        }
S>      else  // scan token, allowed in html: e.g. align=center
S>          do
S>          {
S>              if( is_whitespace(c) ) return TT_ATTR;
S>              if( c == '>' ) { push_back(c); return TT_ATTR; }
S>              append_value(c);
S>          } while(c = get_char());
....
S>      return TT_ERROR;
S>    }
S>


Да, все правильно,
c = scan_entity(); в значениях атрибутов не нужно.

(интересно чем я руководствовался когда его туда воткнул с самого начала?)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.