2012-02-23 5 views
7

좋은 하루! Delphi XE와 Indy TIdHTTP를 사용하고 있습니다. Get 메소드를 사용하여 원격 디렉토리 목록을 얻었고 파일의 크기와 타임 스탬프가 포함 된 파일 목록을 파싱하고 파일과 하위 디렉토리를 구별해야합니다. 제발, 할 일이 좋은가? 미리 감사드립니다. , 나는 그것이 이렇게 될 것이라고 분석 할 수있는 빠른 방법 추측 코드 샘플을 감안할 때HTTP 디렉토리 목록을 구문 분석

<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 /> 
</pre> 
<hr> 
</body> 
+4

샘플이 있습니까? 실제로는 표준 "디렉토리 목록"이 없습니다 (실제로 서버 및 운영 체제에 따라 * 여러 *가 있음). 그리고 작업 중인지 알지 못하고 무엇을 할 수 있는지 말할 필요가 없습니다. 할 필요가. –

+1

필요한 것은 트리를 만드는 HTML 파서이므로 모든 "A"태그를 쉽게 찾고 필요에 따라 작동 할 수 있습니다. – ComputerSaysNo

+1

서버가 WebDAV를 지원하면보다 견고한 솔루션이 WebDAV 클라이언트 라이브러리로 구현하기 쉽습니다. 모든 서버 버전 업데이트 또는 소프트웨어 변경으로 인해이 HTML 출력과 관련된 파서가 손상됩니다. – mjn

답변

7

: Vojtech

여기

는 샘플입니다

  • 가 포함 된 <pre>...</pre> 블록을 식별하는 모든 리스팅 라인. 쉬워야합니다.
  • <pre></pre> 사이의 모든 것을 TStringList에 넣습니다. 각 줄은 파일이나 폴더이며 형식은 매우 간단합니다.
  • 필요한 경우 각 줄에서 링크를 추출하고 날짜, 시간 및 크기를 추출하십시오. Regex (당신은 Regex가 내장되어 있으므로 Delphi XE를 가지고 있습니다)를 사용하면 가장 잘 할 수 있습니다.
+6

+1. 샘플을 가지고 있으면 쉽습니다. 내가 물어 봤니 기쁘지 않니? :) –

7

이 당신에게 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 
------------- 

편집 :을 변경 한
구현은 으로 단순화되었습니다.. 나는 전 버전이 더 에 최적화되어 있다고 믿었습니다. 라인의 길이가 매우 짧다는 사실을 고려하면 성능에는 별다른 차이가 없습니다.

+0

+1이 효과가 있기 때문입니다. 'StripMultipleChar'는 약간 단순화 될 수 있습니다. –

+0

* 단순화 * 최적화 * 할 수 있습니다. * while 루프가 너무 많아서 제 머리가 회전합니다 : 필요한 모든 것은 하나의 단순한 for 루프입니다. –

+0

@Cosmin Prund, 내 편집을 참조하십시오.이전 기능은 실제로 JCL 단위 중 하나를 기반으로했습니다 ... – kobik