Перейти к содержанию
  • Регистрация
  • 0
HyperZen

Регулярное выражение для сайта...

Вопрос

Помогите, пожалуйста, составить регулярное выражение для парсинга сайта https://zadolba.li

Отдельными регулярками вытащить могу всю необходимую информацию, но хотелось бы одним выражением получить и название текста, дату и сам текст, собственно:

procedure TForm1.btnStartClick(Sender: TObject);
var
  HeadMatches, MsgMatches: TMatchCollection;
  CountPagesMatch: TMatch;
  HeadRegularExprString : string;
  MsgRegularExprString : string;
  HTMLText : string;                      // текст для парсинга
begin
    TTask.Run(
      procedure
      var
        aHttp: THTTPClient;
        aStr: TStringStream;
      begin
        aHttp := THTTPClient.Create;
        aStr := TStringStream.Create('', TEncoding.UTF8);
          try
            aHttp.Get('https://zadolba.li', aStr);
            HTMLText := aStr.DataString;
          finally
            aHttp.Free;
            aStr.Free;
        end;

        TThread.Synchronize(TThread.CurrentThread,
          procedure
          var
            i: Integer;
            begin
              mmoText.Lines.Clear;

              HeadRegularExprString := '<h2><a href="\/story.*?>(.*?)<\/a>';

//              MsgRegularExprString := '';

              HeadMatches := TRegEx.Matches(HTMLText, HeadRegularExprString, [roIgnoreCase, roMultiLine]);
//              MsgMatches := TRegEx.Matches(HTMLText, MsgRegularExprString, [roIgnoreCase, roMultiLine]);


//              if HeadMatches.Count = MsgMatches.Count then
//                begin
                    for i := 0 to HeadMatches.Count - 1 do
                      begin
                        mmoText.Lines.Add(HeadMatches.Item[i].Groups[1].Value);
                      end;

//                      end;
                end);
            end);
end;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекомендуемые сообщения

  • 0

В общем получилось две регулярки:

HeadRegularExprString := '<h2><a href="\/story\/.*>(.*?)<\/a>([\s\S]+?).*class=''date-time''>(.*?)<\/div>';
MsgRegularExprString := '<div class=''text''>([\s\S]*?)<\/div>';

HeadMatches := TRegEx.Matches(HTMLText, HeadRegularExprString, [roIgnoreCase, roMultiLine]);
MsgMatches := TRegEx.Matches(HTMLText, MsgRegularExprString, [roIgnoreCase, roMultiLine]);

Все работает корректно, с вышеуказанного сайта парсятся статьи. В TListView создается от 5 до 10 айтемов. Статьи достаточно длинные, TListView начинает безбожно тормозить при скроллинге. Объясните, пожалуйста, почему?!

Изменено пользователем HyperZen

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Вот кот:      )))

procedure TfrmMain.ParsingZadolbali(URLToPars: string; aListView: TListView);
var
  TempText : string;
  HeadMatches, MsgMatches, RatingMatches, NumberCitateMatches: TMatchCollection;
  HeadRegularExprString, NumberCitateExprString, MsgRegularExprString, RatingRegularExprString : string;
begin
  try
    fgActivityDialog1.Message := 'Загрузка цитат...';
    fgActivityDialog1.Show;

    lblParsSite.Text := ZadolbaliOfficialSite;

    TTask.Run(
      procedure
      var
        aHttp: THTTPClient;
        aStr: TStringStream;
      begin
        aHttp := THTTPClient.Create;
        aStr := TStringStream.Create('', TEncoding.UTF8);
          try
            aHttp.Get(URLToPars, aStr);
            HTMLText := aStr.DataString;
          finally
            aHttp.Free;
            aStr.Free;
        end;

        TThread.Synchronize(TThread.CurrentThread,
          procedure
          var
            i: Integer;
            begin
              aListView.Items.Clear;

              HeadRegularExprString := '<h2><a href="\/story\/.*>(.*?)<\/a>([\s\S]+?).*class=''date-time''>(.*?)<\/div>';
              MsgRegularExprString := '<div class=''text''>([\s\S]*?)<\/div>';
              NumberCitateExprString := '<div class=''id''>\s*<span>(.*?)<\/span>';
              RatingRegularExprString := '<div class="rating"><span>(.*?)<\/span>';

              HeadMatches := TRegEx.Matches(HTMLText, HeadRegularExprString, [roIgnoreCase, roMultiLine]);
              MsgMatches := TRegEx.Matches(HTMLText, MsgRegularExprString, [roIgnoreCase, roMultiLine]);
              NumberCitateMatches := TRegEx.Matches(HTMLText, NumberCitateExprString, [roIgnoreCase, roMultiLine]);
              RatingMatches := TRegEx.Matches(HTMLText, RatingRegularExprString, [roIgnoreCase, roMultiLine]);


              for i := 0 to HeadMatches.Count - 1 do
                begin
                  TempText := HTMLClear(MsgMatches.Item[i].Groups[1].Value);

                    with aListView.Items.Add do
                      begin
                        Data['DateText'] := HeadMatches.Item[i].Groups[3].Value;
                        Data['CitateText'] := '№ ' + NumberCitateMatches.Item[i].Groups[1].Value;
                        Data['RatingText'] := '-=' + RatingMatches.Item[i].Groups[1].Value + '=-';
                        Data['MainText'] := HeadMatches.Item[i].Groups[1].Value + sLineBreak + '***********' + TempText + sLineBreak;
                        Data['imgCopy'] := il1.Bitmap(TSizeF.Create(32, 32),0);
                        Data['imgVenzel'] := il1.Bitmap(TSizeF.Create(150, 20),1);
                      end;
                end;

                  ToUp(aListView);  // встаем в начало

                  aListView.Resize;

                  fgActivityDialog1.Hide;
            end);
      end);

    except
      On E: Exception do ShowMessage('Ошибка: ' + E.Message);
    end;
end;

 

Листвью в режиме динамик...

Забыл упомянуть - тормоза только после парсинга сайта zadolba.li, с баша цитаты тянутся по 50 штук - никаких тормозов в листвью нет вообще, все скроллится на изумление гладко :)

Изменено пользователем HyperZen

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Может стоит забить на парсинг html, а использовать специально созданный для таких целей rss интерфейс https://zadolba.li/rss  ?

Там вам все отдается в xml и чудесно раскладывается по полочкам штатными средствами 

Изменено пользователем Евгений Корепов

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Да, интереснее разбирать страницу xml. Но тут дело в другом, именно в тормозах ListView при помещении в его Item большого текста...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
15 часов назад, HyperZen сказал:

Да, интереснее разбирать страницу xml. Но тут дело в другом, именно в тормозах ListView при помещении в его Item большого текста...

Отрендерьте текст в битмап ))))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Так это у всех так? Попробуйте кто-нибудь, пожалуйста, создать 10-15 итемов с текстом, равным статьям с сайта zadolba.li. Тормозит при скроллинге?

Повторюсь - с сайта bash.im статьи тянуться по 50 штук и сразу грузятся в TListView - никаких тормозов нет!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Ну честно, самому лень, и так есть чем заняться)
Скиньте пример - потестим, это же вам в итоге-то надо (не наезд).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Извиняюсь за долгое молчание...

Вот образец, тормозит на андроиде при скроллинге... Посмотрите, пожалуйста.

GraBash.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

у меня почему-то не стояло разрешение ACCESS_NETWORK_STATE

кроме того, вынес парсинг из Synchronize. Запустил на Токио СЕ. Листвью дергается.

Думаю, вполне достаточно было бы без всякого парсинга заполнить его большими объемами LOREM IPSUM , чтобы получить аналогичный эффект

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Очередной раз сайт https://bash.im изменил свою структуру, пытаюсь сделать регулярку для вытаскивания текста цитаты с главной страницы... Не выходит каменный цветок ))) Может кто помочь?

<div class="quote__body">\s*(.*?)\s*<\/div>

Что не так?  На https://regexr.com - все чудненько работает... В Делфи же  - нет!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
31 минуту назад, HyperZen сказал:

Очередной раз сайт https://bash.im изменил свою структуру, пытаюсь сделать регулярку для вытаскивания текста цитаты с главной страницы... Не выходит каменный цветок ))) Может кто помочь?


<div class="quote__body">\s*(.*?)\s*<\/div>

Что не так?  На https://regexr.com - все чудненько работает... В Делфи же  - нет!

Уже выше писал, поворюсь - не нужно стрелять себе в ногу распарсивая разметку сайта. Используйте специально созданный для этого интерфейс https://bash.im/rss/ - XML, он никогда не изменится, один раз написали и забыли.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Спасибо!

Но! Интересен подход именно используя регулярные выражения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 12.08.2018 в 18:55, HyperZen сказал:

В общем, проблема не у меня... Проблема общая. Спасибо за тест!

 

В 12.08.2018 в 18:16, krapotkin сказал:

у меня почему-то не стояло разрешение ACCESS_NETWORK_STATE

кроме того, вынес парсинг из Synchronize. Запустил на Токио СЕ. Листвью дергается.

Думаю, вполне достаточно было бы без всякого парсинга заполнить его большими объемами LOREM IPSUM , чтобы получить аналогичный эффект

Проблема в рендеринге текста. Я с этим столкнулся при написании компонента для чата. FMX не использует нативный вывод текста на Андроиде да и на ИОС тоже. Вердикт применять компоненты с нативной отрисовкой текста.

Я использовал наработки китайского коллеги :

// Firemonkey Native Canvas Class
//
// Copyright 2017 Aone (amtbonechen@gmail.com), 谢顿 (zhaoyipeng@hotmail.com)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Спасибо большое!

А как насчет регулярного выражения для сайта? ))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 31.03.2019 в 16:51, Евгений Корепов сказал:

Уже выше писал, поворюсь - не нужно стрелять себе в ногу распарсивая разметку сайта. Используйте специально созданный для этого интерфейс https://bash.im/rss/ - XML, он никогда не изменится, один раз написали и забыли.

Это все хорошо, но в rss отдается только начальная страница, содержащая 50 цитат... Мне же хочется получать данные и из раздела "Лучшие", "Случайные", "По рейтингу" и пр. Как их вытащить при помощи rss?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
6 часов назад, HyperZen сказал:

Это все хорошо, но в rss отдается только начальная страница, содержащая 50 цитат... Мне же хочется получать данные и из раздела "Лучшие", "Случайные", "По рейтингу" и пр. Как их вытащить при помощи rss?

Вы спрашивали "для вытаскивания текста цитаты с главной страницы", это ввело меня в заблуждение. Можно попробовать использовать параметры в rss запросе (или спросить у поддержки сайта о их наличии). Но согласно стандарту rss, параметров может и не быть. 

Если параметров не окажется - тогда парсинг. Но рекомендую парсинг не регулярными выражениями (ибо тут на удачу), а полноценный парсинг DOM документа (информации в гугле много).

Чтоб не пришлось постоянно изменять и переопубликовывать приложение при смене макета сайта, рекомендую получать и парсить контент сайта на своем сервере (на php эти задачи выполняются очень просто), а приложению отдавать данные в JSON формате (к примеру). При изменении макета сайта вам потребуется несколько минут для исправления php кода на вашем сервере - и приложения будут опять получать правильные данные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Многоуважаемый Евгений! Не могли бы Вы поделиться примером. Гугл не сильно помогает мне что-то сегодня )))

А желательно примером с использованием этого многострадального bash'а  ))

Получилось вот что (Гугл сжалился надо мной )😞

procedure TForm1.Button1Click(Sender: TObject);
var
  doc: OleVariant;
  el: OleVariant;
  i: Integer;
begin
  doc := coHTMLDocument.Create as IHTMLDocument2;
  doc.write(HTML);
  doc.close;
  for i := 0 to doc.body.all.length - 1 do
    begin
      el := doc.body.all.item(i);
      if (el.tagName = 'DIV') and (el.className = 'quote__body') then
      ShowMessage(el.innerText);
    end;
end;
end.

Теперь вопросы (собственно, почему у меня и не получалось ничего):

1) Почему (el.tagName = 'DIV') - необходимо писать именно в верхнем регистре?! В нижнем писал - ничего не работало.

2) Почему результат (el.innerText) нельзя присвоить какой-либо текстовой переменной?

 

Изменено пользователем HyperZen

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 07.04.2019 в 08:16, HyperZen сказал:

1) Почему (el.tagName = 'DIV') - необходимо писать именно в верхнем регистре?! В нижнем писал - ничего не работало.

Потому что 'DIV 'и 'div' - это внезапно разные строки. Я б удивился если бы у вас заработало))) Да че там я, все бы удивились)))

 

В 07.04.2019 в 08:16, HyperZen сказал:

2) Почему результат (el.innerText) нельзя присвоить какой-либо текстовой переменной?

Можно. Просто нужно преобразовать из одного типа в другой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
2 часа назад, Barbanel сказал:

Потому что 'DIV 'и 'div' - это внезапно разные строки. Я б удивился если бы у вас заработало))) Да че там я, все бы удивились)))

Тогда следующий вопрос (смотрим исходный код страницы):

<article class="quote" data-quote="455502">
  <div class="quote__frame">
    <header class="quote__header">
              <a class="quote__header_permalink" href="/quote/455502">#455502</a>
            <div class="quote__header_date">
        18.04.2019 в 11:45
      </div>
    </header>
    <div class="quote__body">
      xxx: Мой кот как-то пару раз написал в углу под компьютерным столом. Так я в тот угол положила грязные носки мужа. Как кот переживал! Целый день время от времени подходил, обнюхивал, жалобно мявкал. Больше в этот угол не гадит.
          </div>

и видим, что все-таки написано div - в нижнем регистре... Пишем в процедуре в нижнем регистре - не работает! И, о чудо, пишем в верхнем (DIV) работает...

Мой мозг зашкаливает ))

2 часа назад, Barbanel сказал:

Можно. Просто нужно преобразовать из одного типа в другой.

Ткните пальцем (кодом) :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...