Форум программистов, компьютерный форум, киберфорум
Наши страницы
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
 
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
#1

RegExp: Парсинг страницы по разным значаниям - Delphi

21.09.2015, 23:20. Просмотров 1101. Ответов 20
Метки нет (Все метки)

Имеется вот такой код на странице:
HTML5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<li class='clear clearfix'>
<span class='row_title'>Группа:</span>
<span class='row_data'>Объявление</span>
</li>
 
<li class='clear clearfix'>
<span class='row_title'>Комментариев: </span>
<span class='row_data'>2</span>
</li>
 
<li class='clear clearfix'>
<span class='row_title'>Просмотров:</span>
<span class='row_data'>93</span>
</li>
 
<li class='clear clearfix'>
<span class='row_title'>Статус:</span>
<span class='row_data'>Включено</span>
</li>
Необходимо спарсить все значения между тегами <span class='row_data'> и </span>.

Проблема вся в том, что на некоторых страницах - тег иногда у "Объявление" разные, к примеру:
HTML5
1
<span class='row_data'><span style="color:#6A011A;font-weight:bold">Платное объявление</span></span>
Помогите пожалуйста примером...
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.09.2015, 23:20
Я подобрал для вас темы с готовыми решениями и ответами на вопрос RegExp: Парсинг страницы по разным значаниям (Delphi):

Парсинг со страницы
Вот сам код стриницы { &quot;status&quot;:&quot;OK&quot;, &quot;data&quot;:{ &quot;messages&quot;:, ...

Парсинг страницы снова
Суть такова - мне нужно парсить большой список страниц (50-280) которые...

Парсинг HTML страницы
Добрый всем день! Блин! Уже какие сутки бьюсь над одной проблемой и не знаю...

Парсинг html-страницы
Здравствуйте, помогите пожалуйста! есть html-текст: &lt;html&gt; &lt;head&gt;...

Парсинг HTML страницы
Имеется следующий текств html странице: &lt;/thead&gt;&lt;tbody&gt;&lt;tr...

Парсинг .asp страницы
Есть страница, вот такая вот - http://automation.whatismyip.com/n09230945.asp ...

20
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
21.09.2015, 23:54  [ТС] #2
Использую:
Delphi
1
2
3
4
5
6
7
8
    RegExp := TRegExpr.Create;
    RegExp.Expression := '<span class='#39'row_data'#39'>(.*?)</span>';
    if RegExp.Exec(HTML) then
    repeat
        FormSetting.Memo1.Lines.Add(RegExp.Match[1]);
    until not RegExp.ExecNext;
    //FreeAndNil(RegExp);
    RegExp.Free;
В первом варианте, всё именно так - как надо:
RegExp: Парсинг страницы по разным значаниям

Однако, если попадается страница с указанным выше (отличимым тегом), то этот код попадает в результат... ((
RegExp: Парсинг страницы по разным значаниям


И ещё вопрос... Как прочитать только первые три значения?
0
VladWH
240 / 190 / 94
Регистрация: 01.05.2015
Сообщений: 732
22.09.2015, 00:23 #3
poreeff, как вариант
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
procedure TForm1.btn1Click(Sender: TObject);
var I,J: Integer; s, val: string;
begin
s := m1.Text;
m2.Clear;
while s<>'' do
 begin
  I := GetVal('<span class=''row_title''>','</span>',s,val);
  if I=0 then Break;
  J := m2.Lines.Add(val);
  Delete(s,1,I);
  I := GetVal('<span class=''row_data''>','</span>',s,val);
  if I=0 then Break;
  m2.Lines.Strings[J] := m2.Lines.Strings[J] + ' ' + val;
  Delete(s,1,I);
 end;
end;
вместо RegExp
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function GetVal(tag1, tag2, str: string; var val: string): integer;
var a,b,l1,l2: Integer;
begin
Result := 0;
a := Pos(AnsiLowerCase(tag1), AnsiLowerCase(str));
if a=0 then exit;
b := PosEx(AnsiLowerCase(tag2), AnsiLowerCase(str), a);
if b=0 then Exit;
l1 := Length(tag1);
l2 := Length(tag2);
val := Copy(str,a+l1,b-a-l1);
if Pos(AnsiLowerCase('span'), AnsiLowerCase(val))>0 then
 begin
  l1 := Pos('>', val);
  val := copy(val, l1+1, length(val));
 end;
Result := b+l2;
end;
1
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 00:52  [ТС] #4
Цитата Сообщение от VladWH Посмотреть сообщение
вместо RegExp...
Немного не то, но, спасибо за вариант...
В программе все происходит на автомате, и надо использовать именно RegExp
Просто мне не понятно как избавиться от лишнего html кода в результате, и ограничить поиск только первыми тремя строками.
0
VladWH
240 / 190 / 94
Регистрация: 01.05.2015
Сообщений: 732
22.09.2015, 04:45 #5
Лучший ответ Сообщение было отмечено poreeff как решение

Решение

Цитата Сообщение от poreeff Посмотреть сообщение
все происходит на автомате
в примере тоже все на автомате происходит...
Цитата Сообщение от poreeff Посмотреть сообщение
надо использовать именно RegExp
вот с использованием RegExp
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
procedure TForm1.btn1Click(Sender: TObject);
var
RegExp: TRegExpr;
begin
 RegExp := TRegExpr.Create;
 RegExp.InputString := m1.Text; m2.Clear;
 RegExp.Expression := '<span.*?row_data.*?>([^<].*?)<';
 if RegExp.Exec then
  repeat
   m2.Lines.Add(RegExp.Match[1]);
  until not RegExp.ExecNext;
 RegExp.Free;
end;
Цитата Сообщение от poreeff Посмотреть сообщение
ограничить поиск только первыми тремя строками
это как?
1
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 08:22  [ТС] #6
Цитата Сообщение от VladWH Посмотреть сообщение
это как?
С этим разобрался, буду использовать delete...

На счет первой строки, так и не понятно...
Посмотрите, всё сразу поймёте

Project1.zip

На некоторых страницах теги у первой строки "Объявления" - разные, из за этого и проблемы, оно просто пропускается...
0
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 08:34  [ТС] #7
Цитата Сообщение от VladWH Посмотреть сообщение
ограничить поиск только первыми тремя строками

это как?
В общем, delete не тот вариант... ((
Имеется в виду чтоб в результат попадали только первые три найденные значения... Все остальные пропускалось (игнорировалось).

Сейчас выводится вот так:
HTML5
1
2
3
4
Объявление
2
93
Включено
А надо без слова "включено" и без всего того - что идет после него... В первом посте я привел пример только 4-рех строк, но на деле их там больше; дата размещения, дата оплаты (если оно платное), до какого периода и т.п.
Понимаете о чем я? )
0
VladWH
240 / 190 / 94
Регистрация: 01.05.2015
Сообщений: 732
22.09.2015, 15:36 #8
Цитата Сообщение от poreeff Посмотреть сообщение
Имеется в виду чтоб в результат попадали только первые три найденные значения... Все остальные пропускалось (игнорировалось).
тогда так
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
procedure TForm1.btn2Click(Sender: TObject);
var RegExp: TRegExpr; I: Integer;
begin
 RegExp := TRegExpr.Create;
 RegExp.InputString := m1.Text; m2.Clear; I:=1;
 RegExp.Expression := '<span.*?row_data.*?>([^<].*?)<';
 if RegExp.Exec then
  repeat
   if I mod 4 <> 0 then m2.Lines.Add(RegExp.Match[1]); Inc(I);
  until not RegExp.ExecNext;
 RegExp.Free;
end;
Цитата Сообщение от poreeff Посмотреть сообщение
но на деле их там больше; дата размещения, дата оплаты (если оно платное),
я вам выше дал код, который подходит и для тех и для других типов объявлений, но вы почему им так и не воспользовались, вот на всякий случай прикрепляю проект, как оно должно быть
1
Вложения
Тип файла: rar RegExp Парсинг страницы по разным значаниям.rar (231.3 Кб, 3 просмотров)
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 19:33  [ТС] #9
Цитата Сообщение от VladWH Посмотреть сообщение
тогда так
Открыл у себя в XE8, и почему то ошибка

RegExp: Парсинг страницы по разным значаниям
Цитата Сообщение от VladWH Посмотреть сообщение
я вам выше дал код
Просто я ответил быстрее чем обратил внимание на "выражение"...))

Прошу прощения но, если не сочтёте за сложность вопроса, подскажите - как мне в результате выводить ответ в мемо вместе с "заголовком" (Со своим или взятым прямо из страницы - без разницы)...

То есть, каждую строку подписывать, что то вроде:
Delphi
1
2
3
4
Memo1.Lines.Add('Группа' +RegExp.Match[1]);
Memo1.Lines.Add('Комментариев', RegExp.Match[2]);
Memo1.Lines.Add('Просмотров', RegExp.Match[3]);
....
Видел как другие это реализуют через SubMatch, но как - знаний с регулярками не хватает((
0
VladWH
240 / 190 / 94
Регистрация: 01.05.2015
Сообщений: 732
22.09.2015, 19:42 #10
Цитата Сообщение от poreeff Посмотреть сообщение
Открыл у себя в XE8, и почему то ошибка
ошибка то какая?
Цитата Сообщение от poreeff Посмотреть сообщение
как мне в результате выводить ответ в мемо вместе с "заголовком" (Со своим или взятым прямо из страницы - без разницы)...
можно так
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.btn2Click(Sender: TObject);
var RegExp: TRegExpr; I: Integer;
const
 Desc: array[1..3] of string = ('Группа: ','Комментариев: ','Просмотров: ');
begin
 RegExp := TRegExpr.Create;
 RegExp.InputString := m1.Text; m2.Clear; I:=1;
 RegExp.Expression := '<span.*?row_data.*?>([^<].*?)<';
 if RegExp.Exec then
  repeat
   if I mod 4 <> 0 then
    begin m2.Lines.Add(Desc[I] + RegExp.Match[1]); Inc(I);
    end else I:=1;
  until not RegExp.ExecNext;
 RegExp.Free;
end;
И все равно вопрос почему именно RegExp? Чем вариант собственного парсинга не устраивает?
1
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 20:13  [ТС] #11
Цитата Сообщение от VladWH Посмотреть сообщение
ошибка то какая?
[dcc32 Error] Unit1.pas(75): E2035 Not enough actual parameters

RegExp: Парсинг страницы по разным значаниям
Цитата Сообщение от VladWH Посмотреть сообщение
можно так
И опять такая же ошибка... У меня почему то не работает ваш код.
Я делаю так:
Но, как в нем подставить названия каждой строки - не знаю.

Кликните здесь для просмотра всего текста
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
procedure TForm1.Button2Click(Sender: TObject);
var
  RegExp: TRegExpr;
  s2: string;
  I: Integer;
begin
    s2:=Memo2.text;
    RegExp := TRegExpr.Create;
    RegExp.Expression := '<span.*?row_data.*?>([^<].*?)<';
      if RegExp.Exec(s2) then
    Memo2.Clear;
      repeat
      if I mod 3 <> 0 then
        Memo2.Lines.Add(RegExp.Match[1]); Inc(I);
      until not RegExp.ExecNext;
    FreeAndNil(RegExp);
end;

Цитата Сообщение от VladWH Посмотреть сообщение
И все равно вопрос почему именно RegExp? Чем вариант собственного парсинга не устраивает?
Не знаю, как то проще показалось с самого начала, что всего пару строк. А со своим - функции писать...
К тому же, парсить я могу а вот с регулярками туго...
0
VladWH
240 / 190 / 94
Регистрация: 01.05.2015
Сообщений: 732
22.09.2015, 20:20 #12
Цитата Сообщение от poreeff Посмотреть сообщение
И опять такая же ошибка... У меня почему то не работает ваш код.
видимо у вас другая версия RegExpr... хотя странно я в архив вложил модуль RegExpr который я использую...
ну пропишите так
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.btn2Click(Sender: TObject);
var RegExp: TRegExpr; I: Integer;
const
 Desc: array[1..3] of string = ('Группа: ','Комментариев: ','Просмотров: ');
begin
 RegExp := TRegExpr.Create;
 RegExp.InputString := m1.Text; m2.Clear; I:=1;
 RegExp.Expression := 'span.*?row_data.*?>([^<].*?)<';
 if RegExp.Exec(m1.Text) then
  repeat
   if I mod 4 <> 0 then
    begin m2.Lines.Add(Desc[I] + RegExp.Match[1]); Inc(I);
    end else I:=1;
  until not RegExp.ExecNext;
 RegExp.Free;
end;
вы точно именно тот проект который я вам отправил открывали? или просто код скопировали из модуля?
1
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 20:35  [ТС] #13
Цитата Сообщение от VladWH Посмотреть сообщение
вы точно именно тот проект который я вам отправил открывали? или просто код скопировали из модуля?
Да, я тоже на это обратил внимание и смотрел сами файлы, вроде все одинаково... Непонятно...
У меня к проекту подключен Synapse, все сохраняется (HTTP.Document.SaveToStream(f);) и преобразовав в "читаемый текст" (if RegExp.Exec(Utf8ToAnsi(f.DataString)) then) парсится в отдельном потоке, чтоб программа не подвисала...
С Вашим кодом (в примере) все прекрасно работает, теперь даже названия каждой строки можно указать свой! Осталось только подправить его под свой RegExpr чтоб заработало...
0
Вложения
Тип файла: zip regexpr.zip (33.4 Кб, 3 просмотров)
VladWH
240 / 190 / 94
Регистрация: 01.05.2015
Сообщений: 732
22.09.2015, 20:45 #14
Цитата Сообщение от poreeff Посмотреть сообщение
С Вашим кодом (в примере) все прекрасно работает, теперь даже названия каждой строки можно указать свой! Осталось только подправить его под свой RegExpr чтоб заработало...
с последним кодом, который я вам дал и с "вашим" RegExpr все будет работать нормально
1
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 20:58  [ТС] #15
Цитата Сообщение от VladWH Посмотреть сообщение
все будет работать нормально
Да, спасибо. Все "вроде" работает. Но, почему то результат выводится два раза подряд...
0
Вложения
Тип файла: zip Project1.zip (36.4 Кб, 3 просмотров)
VladWH
240 / 190 / 94
Регистрация: 01.05.2015
Сообщений: 732
22.09.2015, 21:32 #16
Цитата Сообщение от poreeff Посмотреть сообщение
Но, почему то результат выводится два раза подряд...
сколько у вас совпадений есть столько и выводится, а про заголовки - так они такие и прописаны - одинаковые

Добавлено через 1 минуту
а если хотите другие заголовки, то дополняйте/изменяйте код
0
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 21:36  [ТС] #17
Цитата Сообщение от VladWH Посмотреть сообщение
сколько у вас совпадений есть столько и выводится
Так в том то и дело что нет совпадений, я скинул архив - там вместо значений цифры 1,2,3,4....
про заголовки то оно понятно, но почему он не парсит только (к примеру) первые три значения, почему продолжает дальше бежать по тексту...
А четвертое значение - вообще кануло в лету
0
Миниатюры
RegExp: Парсинг страницы по разным значаниям  
VladWH
240 / 190 / 94
Регистрация: 01.05.2015
Сообщений: 732
22.09.2015, 21:40 #18
Цитата Сообщение от poreeff Посмотреть сообщение
почему он не парсит только (к примеру) первые три значения
потому что вы сами так попросили
Цитата Сообщение от poreeff Посмотреть сообщение
чтоб в результат попадали только первые три найденные значения... Все остальные пропускалось (игнорировалось)
Добавлено через 2 минуты
то есть в объявлении как я понял 4 значения, первые три нужны, а 4-е нет, оно и не пишется... и так для каждого объявления
1
poreeff
3 / 3 / 3
Регистрация: 28.06.2015
Сообщений: 207
22.09.2015, 22:25  [ТС] #19
Цитата Сообщение от VladWH Посмотреть сообщение
потому что вы сами так попросили
Да нет же, Вы не так поняли)
Цитата Сообщение от poreeff Посмотреть сообщение
...только первые три найденные значения... Все остальные пропускалось (игнорировалось).
Только первые три - а остальные не выводились. А вы просто убрали четвертое))
0
NIKOLAYY
819 / 717 / 339
Регистрация: 22.09.2012
Сообщений: 4,994
22.09.2015, 22:43 #20
Цитата Сообщение от poreeff Посмотреть сообщение
Да, спасибо. Все "вроде" работает. Но, почему то результат выводится два раза подряд...
Ну допили под себя чуть код, у меня один раз выводит.

Цитата Сообщение от poreeff Посмотреть сообщение
А четвертое значение - вообще кануло в лету
Слыш а что ты хотел, какое четвертое значение? В этом куске приведенного кода оно даже и неотработает четвертое значение!
Ты на эту строку внимательно смотрел?

Delphi
1
 Desc: array[1..3] of string = ('Группа: ','Комментариев: ','Просмотров: ');
Когда будеш делать inc(i); и у тебя i станет равно четырем- ты выйдеш за пределы массива и получиш ошибку..

Поэтому на я твой код что в архиве у тебя доработал в Делфи-7- У меня все работает. Если версия делфей другая- подпили код под свою версию.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var
  r: TRegExpr;
  i: Integer;
const
  Desc: array[1..4] of string = ('Группа: ', 'Комментариев: ', 'Просмотров: ', 'Статус: ');
    
begin
  i := 0;
  Memo2.Clear;
  r := TRegExpr.Create;
  r.InputString := Memo1.Text; //где ищем
  r.Expression := 'span.*?row_data.*?>([^<].*?)<';
 
  if r.Exec then
    repeat
      inc(i);
      Memo2.Lines.Add(Desc[i] + r.Match[1]);
      if i = 4 then
      Break;
    until not r.ExecNext;
end;
Цитата Сообщение от poreeff Посмотреть сообщение
Так в том то и дело что нет совпадений, я скинул архив - там вместо значений цифры 1,2,3,4....
И это плохо что ты так сделал, надо было как есть, там в именах наверняка есть русские буквы, тогда и рег шаблон можно было бы по другому составлять.

Цитата Сообщение от poreeff Посмотреть сообщение
То есть, каждую строку подписывать, что то вроде:
Memo1.Lines.Add('Группа' +RegExp.Match[1]);
Memo1.Lines.Add('Комментариев', RegExp.Match[2]);
Memo1.Lines.Add('Просмотров', RegExp.Match[3]);


Да так тоже можно в разные матчи тоже складывать но тока не в твоем случае.
1
Миниатюры
RegExp: Парсинг страницы по разным значаниям  
22.09.2015, 22:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.09.2015, 22:43
Привет! Вот еще темы с решениями:

Парсинг данных со страницы Вконтакте
Привет ребята, такая штука хочу программно спарсить данные со страницы...

Парсинг данных с html-страницы
доброго времени суток! Есть страница. Часть. &lt;script&gt; var...

Парсинг HTML страницы с rutracker.org
Здравствуйте, нужно пропарсить страницу rutracker'a, Нужны значения после Год...

Парсинг определенных символов с веб страницы
Всем привет. Есть веб страница, на ней есть строка вида login@domain.ru;pass...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru