Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Работа с DIRegEx -библиотека регулярных выражений для Delphi

Автор: X11
Дата сообщения: 26.09.2009 00:47
DIRegEx

Не найдётся ли у кого более-менее простых примеров для работы с этими компонентами.
Например, есть страница HTML.
Нужно отпарсить её, и в цикле получить все ссылки.
Указать начальные данные несложно:

регулярное выражение
DIPerlRegEx1.MatchPattern := '.......';

текст, в котором будем искать
DIPerlRegEx1.SetSubjectStr();

А вот как правильно получить результат и выполнить цикл по всем совпадениям?
Автор: X11
Дата сообщения: 28.09.2009 19:16
Как правильно узнать количество совпадений?
Автор: KF121
Дата сообщения: 29.09.2009 22:25
Regex:=TDIPerlRegEx.Create(nil);
Regex.SetSubjectStr(Strings.Text);
Regex.Options:=[poCaptureSubstrings];
Regex.CompileOptions:=[coCaseLess, coMultiline, coDotAll];

{Functions search}
i:=0;
if cFunc<>'' then begin
Regex.MatchPattern:=cFunc;
if not regex.CompileMatchPattern then StatusBar.Panels[8].Text:='FuncDetect error ' + IntToStr(RegEx.ErrorCode) + ': ' + RegEx.ErrorMessage + ' (at ' + IntToStr(RegEx.ErrorOffset + 1) + ').'
else if Regex.Match(0)>=0 then begin
repeat
if Attrib then edit.GetHighlighterAttriAtRowCol(edit.CharIndexToRowCol(Regex.SubStrFirstCharPos(0)), s, attri);
if assigned(attri) then begin
attri.Name:=LowerCase(attri.Name);
if (pos('string',attri.Name)=0)and
(pos('comment',attri.Name)=0)and
(pos('remark',attri.Name)=0)
then if AddFunc(PfmMain, Node, regex, Strings, Attrib, fn) then inc(i);
end
else if AddFunc(PfmMain, Node, regex, Strings, Attrib, fn) then inc(i);
until (Regex.MatchNext<0)or(i=1024)or(KeyTime=0);
if i>=1024 then begin
StatusBar.Panels[8].Text:='Too many functions found! First 1024 parsed.';
MessageBeep(MB_ICONEXCLAMATION);
end
end;
if cSortTree then Node.AlphaSort(true);
Node.Expanded:=FuncExp;
end;

ну вроде этого что-то.
Автор: X11
Дата сообщения: 29.09.2009 23:37
DiRegEx 4.3, D2007.

Парсинг HTML.
Вот регулярка: (?i)(http:.*?>Следующая)
Исходный текст отсюда: irr.ks.ua/Default.aspx?Rubric=2&SubRubric=38
Когда тестирую выражение в DiRegEx Workbench, то всё прекрасно. Эта программа находит и возвращает одну нужную строку (ссылку на след. страницу).
Если в регулярку добавить модификатор s, то Workbench выводит в результат сразу несколько строк (?si)(http:.*?>Следующая)

А вот, когда я в своей программе выполняю парсинг, то ВСЕГДА rexp.MatchedStr возвращает не одну нужную строку, а многострочный текст: от самого начала текста (от первого http) и до слова "Следующая".

Вот функция

Код:
function ParseByDI(InputString: string; MatchPattern: string): TParsedArray;
var
rexp: TDIRegEx;
tempArray: TParsedArray;
count, i: Integer;
begin
rexp := TDIPerlRegEx.Create(nil);
try
rexp.SetSubjectStr(InputString);
rexp.MatchPattern := MatchPattern;



//даже при явном отключении многострочности в результате появляется не 1, а много строк
rexp.CompileOptions := rexp.CompileOptions - [coDotAll];



if rexp.Match(0) < 0 then
begin
//если нет совпадений
SetLength(TempArray, 1);
tempArray[count].Ind := 0;
tempArray[count].Len := 0;
tempArray[count].Match := '';
exit;
end;

count := 0;
repeat// пока есть совпадению
SetLength(TempArray, count+1);
tempArray[count].Ind := count;
tempArray[count].Len := Length(rexp.MatchedStr);
tempArray[count].Match := rexp.MatchedStr;

Inc(count);
until rexp.MatchNext < 0;
Result := TempArray;
finally
FreeAndNil(rexp);
end;
end;
Автор: kruzen33
Дата сообщения: 02.10.2009 09:13
куда я впёрся...
Автор: X11
Дата сообщения: 14.01.2010 16:33
Есть строка
. ул. Дорофеева, малосемейка, 5/9, 32/18/6, после ремонта, лифт не работает, новая металлическая дверь, линолеум, кафель, батареи, вода постоянноЦена: 20500 $. Тел:5645456456456, Сайт: <atarget="_blank" href="http://www.info-broker.ks.uawww.info-broker.ks.ua, . office @ info-broker ks ua

вот образец: Сайт.*?,

Вот функция замены:

Код:
function ReplaseByDi2(const InputStr: String; const MatchPattern: String;const NewString: String): String;
var
RE: TDIPerlRegEx;
AOptions: TDIRegexCompileOptions;
begin
//RegExReplace('Apple', '\bapple\b', 'orange', [coCaseLess]);
//http://bbs.cnsoftware.cn/thread-217-1-1.html

RE := TDIPerlRegEx.Create(nil);
try
RE.SetSubjectStr(InputStr);
AOptions := {[coCaseLess];}[coCaseLess, coMultiline, coDotAll];
RE.CompileOptions := AOptions;

if not RE.CompileMatchPatternStr(MatchPattern) then showMessage('Ошибка RE.CompileMatchPatternStr');

RE.FormatPattern := NewString;



//здесь всегда 0

if RE.Replace2(Result) = 0 then
Result := InputStr;




finally
RE.Free;
end;
end;
Автор: data man
Дата сообщения: 15.01.2010 02:37
X11
Цитата:
Хотя в демке Workbench замена работает.

1. А в демке такие-же опции установлены ?
2. Какая версия Delphi и DIRegEx ?
Потому как:

Цитата:
DIRegEx 5.1.1 – 29 Oct 2009
Change published TDIRegEx.MatchPattern property back to AnsiString. This was unfortunately required type to fix a Delphi 2009 / 2010 RawByteString streaming problem.
Add new public TDIRegEx.MatchPatternRaw: RawByteString property to allow Unicode Delphis to set the MatchPattern without automatic codepage conversion. This is now the recommended MatchPattern runtime property.
и
Цитата:
DIRegEx 5.0.1 – 31 Jan 2009
Work around an unexpected Delphi 2009 automatic numeric AnsiChar Unicode conversion in DIUtils.pas which caused an error when compiled on a Windows OS set to a non-European (Asian, Cyrillic, etc.) codepage.
3. И если это "стянутая" страница, может лучше использовать DIHtmlParser (в обменнике есть) ?
Автор: X11
Дата сообщения: 15.01.2010 09:17

Цитата:
1. А в демке такие-же опции установлены ?

Да.


Цитата:
2. Какая версия Delphi и DIRegEx ?

Д2070 + DiRegEx 4.3

Добавлено:
Я вот что сделал, обрамил выражение скобками, вот так: (Сайт.*?,)
И парсинг заработал. Хотя workbench работает и без скобок.

data man, ты случайно не знаешь, можно ли параметры модификации в выражении? Типа так первое выражение в скобках):
(?msr)(<td><span.*?</span></td>)
Автор: data man
Дата сообщения: 15.01.2010 10:07
X11

Не совсем понял про какие параметры речь, и в каком выражении.
Если в выражении замены, то нет - нельзя.
Лучше так: что требуется ? Замена ссылок на что-то ?


Цитата:
Д2070

А где такую скачать можно ?
Автор: X11
Дата сообщения: 15.01.2010 10:20

Цитата:
Не совсем понял про какие параметры речь, и в каком выражении.

Ключи модификации, или как они правильно называются. Это m, i, r, s.



Цитата:
Лучше так: что требуется ? Замена ссылок на что-то ?

Требуется замена текста. А правильнее - удаление лишнего текста (мусора) из текста объявления.
Есть парсер сайтов. Нужно выдёргивать тексты объявлений.

Добавлено:

Цитата:
А где такую скачать можно ?

Лет через 60 скачаем ))))))

У меня Д2007
Автор: data man
Дата сообщения: 15.01.2010 11:13
X11
Модификаторы, да, можно. И ставить минус перед ними для инвертирования их значения.


Цитата:
Нужно выдёргивать тексты объявлений.

IMHO, для этого DIHtmlParser лучше всего подходит.
И тэги правильно обрабатывает, плагины есть и для таблиц и для извлечения линков.
Да и работает очень быстро.
В общем рекомендую.
Автор: X11
Дата сообщения: 15.01.2010 11:36
А есть ещё DITidy, что это за..
Автор: data man
Дата сообщения: 15.01.2010 11:50
X11
Это обёртка над популярной Сишной libtidy, парсит XML, HTML и XHTML.
Не OOP - только функции и процедуры.
Вот такой пример извлечения ссылок из файла [more]
Код: program DITidy_Extract_Links;

{$APPTYPE CONSOLE}
{$I DI.inc}

uses
{$IFDEF FastMM}FastMM4, {$ENDIF}SysUtils, DITidy;

{ Calls itself recursively to iterate all children of a given node.
Each node is checked for links, which are written out to the console. }
procedure WriteLinks(const ANode: TidyNode);
var
a: TidyAttr;
c: TidyNode;
begin
c := tidyGetChild(ANode);
while Assigned(c) do
begin

case
tidyNodeGetType(ANode) of
TidyNode_Start, TidyNode_StartEnd:
case tidyNodeGetId(ANode) of
TidyTag_A:
begin
a := tidyAttrGetByID(ANode, TidyAttr_HREF);
if Assigned(a) then
WriteLn(tidyAttrValue(a));
end;
end;
end;

{ Now for the children ... }
WriteLinks(c);
c := tidyGetNext(c);
end;
end;

label
lblDone;
var
Doc: TidyDoc;
ErrorBuffer: TidyBuffer;
FileName: string = '';
RC: Integer;
begin
if
ParamCount <> 1 then
begin
WriteLn('Usage: ', ExtractFileName(ParamStr(0)), ' <File>');
goto lblDone;
end;
FileName := ParamStr(1);

Doc := tidyCreate;
RC := tidySetErrorBuffer(Doc, @ErrorBuffer);

if RC >= 0 then
begin
{ Parse the file. }
RC := tidyParseFile(Doc, PAnsiChar(AnsiString(FileName)));
{ Show potential warnings and errors. }
WriteLn(PAnsiChar(ErrorBuffer.bp));

{ If document loaded OK, write out its links. }
if RC >= 0 then
begin
WriteLn;
WriteLn('Links in ', FileName, ':');
WriteLn;
WriteLinks(tidyGetRoot(Doc));
end;
end;

tidyBufFree(@ErrorBuffer);
tidyRelease(Doc);

lblDone:
WriteLn;
WriteLn('Done - Press ENTER to exit');
ReadLn;
end.

Автор: X11
Дата сообщения: 06.01.2012 13:22
Странно себя ведёт эта библиотека со знаком номера №

Вот исходный текст:

Цитата:
04.01.2012 № 176853, Москва ,


Вот выражение:

Код: \d[\d() ]{6,}

Страницы: 1

Предыдущая тема: Не компилится .PAS файл в C++ Builder 2009


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.