Разобрать список каталогов HTTP - PullRequest
7 голосов
/ 23 февраля 2012

Добрый день! Я использую Delphi XE и Indy TIdHTTP. Используя метод Get, я получаю удаленный список каталогов, и мне нужно проанализировать его = получить список файлов с их размерами и временными метками, а также различать файлы и подкаталоги. Пожалуйста, есть хороший способ сделать это? Заранее спасибо! Войтех

Вот образец:

<code><head>
  <title>127.0.0.1 - /</title>
</head>
<body>
  <H1>127.0.0.1 - /</H1><hr>
<pre>      
  Mittwoch, 30. März 2011    12:01        &lt;dir&gt; <A HREF="/SubDir/">SubDir</A><br />
  Mittwoch, 9. Februar 2005    17:14          113 <A HREF="/file.txt">file.txt</A><br />

Ответы [ 2 ]

7 голосов
/ 24 февраля 2012

Это должно дать вам хорошее начало и идею, используя DOM:

uses
  MSHTML,
  ActiveX,
  ComObj;

procedure DocumentFromString(Document: IHTMLDocument2; const S: WideString);
var
  v: OleVariant;
begin
  v := VarArrayCreate([0, 0], varVariant);
  v[0] := S;
  Document.Write(PSafeArray(TVarData(v).VArray));
  Document.Close;
end;

function StripMultipleChar(const S: string; const C: Char): string;
begin
  Result := S;
  while Pos(C + C, Result) <> 0 do
    Result := StringReplace(Result, C + C, C, [rfReplaceAll]);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Document: IHTMLDocument2;
  Elements: IHTMLElementCollection;
  Element: IHTMLElement;
  I: Integer;
  Line: string;
begin
  Document := CreateComObject(CLASS_HTMLDocument) as IHTMLDocument2;
  DocumentFromString(Document, '<head>...'); // your HTML here

  Elements := Document.all.tags('A') as IHTMLElementCollection;
  for I := 0 to Elements.length - 1 do
  begin
    Element := Elements.item(I, '') as IHTMLElement;
    Memo1.Lines.Add('A HREF=' + Element.getAttribute('HREF', 2));
    Memo1.Lines.Add('A innerText=' + Element.innerText);

    // Text is returned immediately before the element
    Line := (Element as IHTMLElement2).getAdjacentText('beforeBegin');

    // Line => "Mittwoch, 30. März 2011 12:01 <dir>" OR:
    // Line => "Mittwoch, 9. Februar 2005 17:14 113"...
    // I don't know what is the actual delimiter:
    // It could be [space] or [tab] so we need to normalize the Line
    // If it's tabs then it's easier because the timestamps also contains spaces

    Line := Trim(Line);
    Line := StripMultipleChar(Line, #32); // strip multiple Spaces sequences
    Line := StripMultipleChar(Line, #9);  // strip multiple Tabs sequences

    // TODO: ParseLine (from right to left)

    Memo1.Lines.Add(Line);
    Memo1.Lines.Add('-------------');
  end;
end;

Выход:

A HREF=/SubDir/
A innerText=SubDir
Mittwoch, 30. März 2011 12:01 <dir>
-------------
A HREF=/file.txt
A innerText=file.txt
Mittwoch, 9. Februar 2005 17:14 113
-------------

EDIT:
Я изменил StripMultipleChar реализацию, чтобы быть более упрощенным . все же я верю, что предыдущая версия была более оптимизирована для скорости. учитывая тот факт, что линии очень короткие по длине, различий в производительности не будет.

7 голосов
/ 23 февраля 2012

Учитывая пример кода, я думаю, самый быстрый способ разбора будет выглядеть так:

  • Идентифицирует блок ..., содержащий все строки списка. Должно быть легко.
  • Поместите все между <pre> и </pre> в TStringList. Каждая строка представляет собой файл или папку, и формат очень прост.
  • Извлечение ссылок из каждой строки, извлечение даты, времени и размера, если вам это нужно. Лучше всего делать с регулярным выражением (у вас есть Delphi XE, поэтому у вас есть встроенное регулярное выражение).
...