Столкнулся с задачей. Следует спарсить данные на странице, данные находятся между тегами <teg1> и <teg2>. Загвоздка состоит в том, что таких данных на странице достаточно много... Подскажите как спарсить все необходиые данные между тегами <teg1> и <teg2>. Движусь так... Код: Code: s:=IdHTTP1.Get('http://sait.ru/catalog); s:=copy(s,pos('<teg1>',s)+length('<teg1>'),pos('<teg2>',s)-length('<teg2>')); Но ничего не выходит...
Code: s:=IdHTTP1.Get('http://sait.ru/catalog); while (pos('<teg1>',s)>0) and (pos('<teg2>',s)>0) do begin ss:=copy(s,pos('<teg1>',s)+length('<teg1>'),pos('<teg2>',s)-length('<teg2>')-1); showmessage(ss); //тут сделаешь с этим значением то, что нужно delete(s,1,pos('<teg2>',s)+length('<teg2>')-1); end; а вкратце: кроме copy надо еще и удалять те теги, которые не нужны т.е. <teg1>a<teg2><teg1>b<teg2><teg1>c<teg2><teg1>d<teg2> a скопировал, удалил <teg1>a<teg2> b скопировал, удалил <teg1>b<teg2> и т.д.
Пользуюсь такой функцией: T_ - открывающий тег ForS - исходный текст _T - закрывающий текст Ищет первое вхождение Code: function Pars(T_, ForS, _T: string): string; var a, b: integer; begin Result := ''; if (T_ = '') or (ForS = '') or (_T = '') then Exit; a := Pos(T_, ForS); if a = 0 then Exit else a := a + Length(T_); ForS := Copy(ForS, a, Length(ForS) - a + 1); b := Pos(_T, ForS); if b > 0 then Result := Copy(ForS, 1, b - 1); end;
Code: function Pars(T_, ForS, _T: string): string; var a, b: integer; begin Result := ''; if (T_ = '') or (ForS = '') or (_T = '') then Exit; a := Pos(T_, ForS); if a = 0 then Exit else a := a + Length(T_); ForS := Copy(ForS, a, Length(ForS) - a + 1); b := Pos(_T, ForS); if b > 0 then Result := Copy(ForS, 1, b - 1); end; s:=IdHTTP1.Get('http://sait.ru/catalog); t:=Pars ( '<teg1>', s, '<teg3>' );
Wait, вы не читаете первый пост, а жаль. Сам пользуюсь этой функцией, переделал в ней: 1) при пустом T_ или _T парсится от начала или до конца соответственно; 2) ввел CaseSensitive:boolean, для того, чтобы можно было искать не заботясь о регистре букв. Но ТС интересно было именно как распарсить все значения со страницы, а не только 1е (которое выдавале его copy(....) и выдаст Pars(....)) хотя как вариант можно переделать мой цикл под использование Pars(...) но смысла это не изменит если кому интересно вот переделанная ф-ия Pars: Code: function Pars(T_, ForS, _T: string; CaseSensitive:Boolean): string; var a, b: integer; begin Result := ''; if (ForS = '') then Exit; if T_='' then a:=1 else if CaseSensitive then a := Pos(T_, ForS) else a := Pos(UpperCase(T_), UpperCase(ForS)); if a = 0 then Exit else a := a + Length(T_); ForS := Copy(ForS, a, Length(ForS) - a + 1); if _T='' then b:=Length(forS)+1 else if CaseSensitive then b := Pos(_T, ForS) else b := Pos(UpperCase(_T), UpperCase(ForS)); if b > 0 then Result := Copy(ForS, 1, b - 1); end; Как видно, даже при CaseSensitive:=true; результатом будет строка с символами в том же регистре, что и в оригинале.
Я тут один про PosEx знаю? Вот функция, примерно такой же объем кода но парсит все вхождения, возвращает TStrings, не забываем проверять на nil и освобождать Code: function Parse(const tag1, tag2, source: string): TStrings; var p, p2, len: Integer; begin Result := nil; p := Pos(tag1, source); len := Length(tag1); p2 := PosEx(tag2, source, p + len + 1); if (p = 0) or (p2 = 0) then Exit; Result := TStringList.Create; while (p > 0) and (p2 > 0) do begin if p2 > p then Result.Add(Copy(source, p + len, p2 - p - len)); p := PosEx(tag1, source, p2); p2 := PosEx(tag2, source, p + len + 1); end; end; Пример использования: Code: var strings: TStrings; begin strings := Parse('<a href="', '"', Memo1.Lines.Text); if strings <> nil then begin Memo2.Lines.AddStrings(strings); strings.Free; end; end; PS А вообще, такие вещи обычно решаются с помощью регулярок
О, спасибо! Похоже что из всех присутствующих только ты )) P.S. До регулярок дорасти еще надобно, пока и без них головняка хватает.
ну регулярками куда удобнее. Я раньше тоже через Pos, Copy работал а регулярок "бояслся" думал что сложно А вот маска регулярки под вашу задачу: <teg1>(.*)<teg2>
Kakeola, а где подробнее можно почитать по поводу регулярок? а то я как раз тож боюсь, и нигде на глаза толковой литературы по этому поводу не попадалось
вот эта ссылка хорошая - http://forum.vingrad.ru/forum/act-ST/f-84/t-213075.html я ее читал. А вообще будут вопросы - спрашивай на винграде ибо тут тебе скажут как ломануть)))) А там специалисты широкого профиля и улучшенно подскажут как и что и какие ссылки почитать
А если без регулярок то логика такая: Псевдокод: Измеряем длину <tag1> Метка1: Находим позицию <tag1> К позиции <tag1> прибавляем длину <tag1> получаем указатель на нужные данные X Находим позицию <tag2> и заносим на ее место байт 0 считываем данные по указателю X Повторяем весь поиск начиная с позиции <tag2> + 1 (Переход на Метка1) пока любой поиск не вернет ошибку