Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.09.19;
Скачать: CL | DM;

Вниз

Медленный парсер HTML   Найти похожие ветки 

 
BorisMor ©   (2004-08-30 10:35) [0]

Требуется отделить текст от тегов. Написал простенький парсер, но как то все медленно работает.
Ищем <, затем >  - это есть тег. Все что не входит между этими символами то текст.
Основная функция разбора:


// Находит в sIn символ sSep. То что справа оставляет в sIn, на выходе то что слева
// Если sSep нет в sIn то sIn становится пустым, на выходе вся строка
function ParseToken(var sIn :string; sSep:string):string;
var
s:string;
i:integer;
begin
i:=Pos(sSep,sIn);
if i=0 then
 begin
  result:=sIn;
  sIn:="";
  exit;
 end
else
 begin
  result := Copy(sIn,1,i-1);
  sIn :=Copy(sIn,i+Length(sSep),Length(sIn));
 end;
end;


Может посоветуете что побыстрей ?


 
DiamondShark ©   (2004-08-30 10:47) [1]

mshtml


 
Erik1   (2004-08-30 10:58) [2]

А ошибки ты вобще неучитываеш, что будет если у тебя 3 тега? Основной совет, неныделяй память заного! Даи функция у тебя маленькая, ее сложно оптимизировать. Я думя, что ее надо расматривать вместе с верхним циклом в котором вызывается эта функция.
 Я еще лучще взять готовый парсер HTML и немучатся.


 
Romkin ©   (2004-08-30 11:19) [3]

НАвскидку:


type
 TAuState = (ausInLine, ausInTag);

function RemoveTags(const S: string): string;
var
 AState: TAuState;
 i, k: integer;
begin
 SetLength(Result, length(S));
 if S = "" then exit;
 AState := ausInLine;
 k := 0;
 for i := 1 to length(S) do
   case AState of
     ausInLine: begin
       if S[i] <> "<" then
       begin
         inc(k);
         Result[k] := S[i];
       end
       else
         AState := ausInTag;
     end;
     ausInTag: begin
       if S[i] := ">" then
         AState := ausInLine;
     end;  
   end; //case
 SetLength(Result, k);
end;

Вроде работать должно ;)


 
GuAV ©   (2004-08-30 11:29) [4]


> Result[k] := S[i];

Это будет тормозить, т.к. там UniqueString будет.
Если  [3] работает, то то что в for переписать на asm-е или хотя бы PChar юзануть.


 
Romkin ©   (2004-08-30 11:33) [5]

Будет, но не слишком :)) Как войдет - так и выйдет.
Что, переписать на TMemoryStream? :)


 
nicesc   (2004-08-31 12:01) [6]

Romkin
При большом объеме будешь доолго ждать

GuAV
Полностью согласен


 
Romkin ©   (2004-08-31 12:14) [7]

nicesc  (31.08.04 12:01) [6] Долго? Эт сколько? И при каком объеме? Поконкретнее, плиз

Ладно, уговорили. Для боольших объемов:

type
TAuState = (ausInLine, ausInTag);

function RemoveTags(const S: string): string;
var
AState: TAuState;
i, k: integer;
Stream: TStream;
begin
 Result := "";
 if S = "" then exit;
 Stream := TMemoryStream.Create;
 try  
   Stream.Size := Length(S);
   Stream.Position := 0;
   AState := ausInLine;
   k := 0;    
   for i := 1 to Length(S) do
   case AState of
     ausInLine: begin
       if S[i] <> "<" then
       begin
         inc(k);
         Stream.Write(S[i],1);
       end
       else
       AState := ausInTag;
     end;
     ausInTag: begin
       if S[i] := ">" then
         AState := ausInLine;
     end;  
   end; //case
   SetLength(Result, k);
   Stream.Position := 0;
   Stream.Read(Result[1], Length(Result));
 finally
   Stream.Free;
 end;
end;


Но скорость и первого варианта также вполне достаточна для большинства случаев ;)


 
GuAV ©   (2004-08-31 12:18) [8]


> Что, переписать на TMemoryStream? :)

Да нет, я же сказал на asm :)


 
Romkin ©   (2004-08-31 12:21) [9]

Впрочем, пройдет вроде и такое:

type
TAuState = (ausInLine, ausInTag);

function RemoveTags(const S: string): string;
var
AState: TAuState;
i, k: integer;
begin
SetLength(Result, length(S));
if S = "" then exit;
AState := ausInLine;
k := 0;
for i := 1 to length(S) do
 case AState of
  ausInLine: begin
   if S[i] <> "<" then
   begin
    PByte(pointer(Result) + k)^ := byte(S[i]);
    inc(k);
   end
   else
    AState := ausInTag;
  end;
  ausInTag: begin
   if S[i] := ">" then
    AState := ausInLine;
  end;  
 end; //case
SetLength(Result, k);
end;


Но опять же: не люблю указатели, аккуратственнее надо :))


 
Romkin ©   (2004-08-31 12:25) [10]

GuAV ©  (31.08.04 12:18) [8] Перепиши и сравни, много ли выиграешь? Несколько процентов? А надо ли? Чем понятнее программа, тем лучше.
Попробуй, разберись, что тут делается:
http://delphibase.endimus.ru/?action=viewfunc&topic=strsearch&id=10271
:))


 
GuAV ©   (2004-08-31 13:09) [11]


> http://delphibase.endimus.ru/?action=viewfunc&topic=strsearch&id=10271
> :))

Вобщем то понятно ошибок не вижу. Сам подобное писал.
Я бы не извращался с LODSB и ESI.

А запутать на ООП можно лудше чем на asm, на то оно и ООП :->


 
GuAV ©   (2004-08-31 13:14) [12]


> Я бы не извращался с LODSB и ESI.

Виноват, это когда до         REPE CMPSB не дошел.


 
GuAV ©   (2004-08-31 13:16) [13]

procedure ThousandAsm(var P: string);
asm
       PUSH   ESI
       MOV    ESI, EAX
       MOV    EAX, [EAX]
       CALL   System.@LStrLen
       CMP    EAX, 3
       JLE    @@1

       PUSH   EDI
       MOV    EDI, EAX

       MOV    ECX, 3
       XOR    EDX, EDX
       DEC    EAX
       DIV    ECX

       PUSH   EAX

       MOV    EDX, EDI
       ADD    EDX, EAX

       MOV    EAX, ESI
       CALL   System.@LStrSetLength

       ADD    EDI, [ESI]
       POP    ECX

       DEC    EDI       // Предопследний
 @@0:  SUB    EDI, 3    // На три символа к началу
       MOV    EDX, [EDI].DWord // Взять четыре символа
       MOV    DL, ThousandSeparator // Первый заменить пробелом
       MOV    [EDI+ECX].DWord, EDX // И вернуть на ECX выше
       DEC    ECX
       JNZ    @@0
       POP    EDI
 @@1:
       POP    ESI
end;

// отделяет части числа пробелами
// для значений до 1 млрд быстрее FloatToStrF

function Thousand(Int: Int64): string;
begin
 Result:=IntToStr(Int);
 ThousandAsm(Result);
end;


 
atruhin ©   (2004-08-31 13:16) [14]

Зачем придумывать лишнее? Я бы рекомендовал то же что и  Erik1   (30.08.04 10:58) [2]
Если нужно писать самостоятельно то посмотри либо:
RegExp - модуль для работы с регулярными выражениями
Либо есть модуль с большим кол-вом функций для парсинга написанный (c) Alex Konshin mailto:alexk@mtgroup.ru
http://www.mtgroup.ru/~alexk/
И то и другое превзойти по скорости и безглючности поверьте сложно.


 
Mim1 ©   (2004-08-31 19:21) [15]

Меня так же интересует эта тема. Мне в отличии от автора требуется сделать XML прасер или использовать готовый. Сейчас использую LibXmlParser с www.destructor.de.

Однако надеюсь, если будет время написать свой.

[14] atruhin ©   (31.08.04 13:16)

Ничего связанного с разбором не нашел. :( Хотя сайт очень понравился. Жалко что ничего из расположенного там не компилируется под delphi 7. Очень мне интересен его хитрый грид, на выходных попробую подправить исходники.

PS от мелкомягких парсилку заюзать не могу т.к. проект CLXный.



Страницы: 1 вся ветка

Текущий архив: 2004.09.19;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.055 c
3-1092907138
Loaderz
2004-08-19 13:18
2004.09.19
Где здесь Ошибка???


1-1094558392
Прямой
2004-09-07 15:59
2004.09.19
Можно ли главной формой сделать Form2


1-1094041136
Cherepah
2004-09-01 16:18
2004.09.19
Сохранение массива Record в файл


4-1091439355
o_nick
2004-08-02 13:35
2004.09.19
ThreadID


10-1038816487
Calm
2002-12-02 11:08
2004.09.19
Материалы в помощь начинающим. Где их взять?