2012-02-23 33 views
7

Ngày tốt lành! Tôi đang sử dụng Delphi XE và Indy TIdHTTP. Sử dụng phương thức Get Tôi nhận danh sách thư mục từ xa và tôi cần phải phân tích cú pháp nó = lấy danh sách các tệp có kích thước và dấu thời gian của chúng và phân biệt tệp và thư mục phụ. Xin vui lòng, có một thói quen tốt để làm điều đó? Cảm ơn bạn trước! VojtechDanh sách thư mục Parse HTTP

Dưới đây là các mẫu:

<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

Bạn có mẫu không? Không thực sự là một danh sách "danh sách thư mục" tiêu chuẩn (thực ra, có * vài *, tùy thuộc vào máy chủ và hệ điều hành đang chạy) và không biết bạn đang làm việc với điều gì cần làm. –

+1

những gì bạn cần là một trình phân tích cú pháp HTML tạo ra một cây, vì vậy sẽ dễ dàng tìm thấy tất cả các thẻ "A" và hành động theo nhu cầu của bạn. – ComputerSaysNo

+1

Nếu máy chủ hỗ trợ WebDAV, một giải pháp mạnh mẽ hơn sẽ dễ thực hiện với thư viện ứng dụng WebDAV. Mọi cập nhật phiên bản máy chủ hoặc thay đổi phần mềm sẽ phá vỡ trình phân tích cú pháp cụ thể cho đầu ra HTML này. – mjn

Trả lời

7

Với mẫu mã, tôi đoán nhanh nhất cách để phân tích nó sẽ là như thế này:

  • Xác định khối <pre>...</pre> chứa tất cả các liệt kê các dòng. Nên dễ dàng.
  • Đặt mọi thứ giữa <pre></pre> vào một số TStringList. Mỗi dòng là một tệp hoặc thư mục và định dạng rất đơn giản.
  • Trích xuất các liên kết từ mỗi dòng, trích xuất ngày, giờ và kích thước nếu bạn cần. Thực hiện tốt nhất với một regex (bạn đã có Delphi XE, do đó bạn đã có được xây dựng trong Regex).
+6

+1. Thật dễ dàng khi bạn có một mẫu. Bạn có vui không? :) –

7

này sẽ cho bạn một khởi đầu tốt và ý tưởng sử dụng 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; 

Output:

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:
Tôi đã thay đổi StripMultipleChar triển khai được nhiều hơn đơn giản hóa. nhưng tôi tin rằng phiên bản cũ hơn là được tối ưu hóa để tăng tốc. xem xét thực tế là các dòng có độ dài rất ngắn, sẽ không có nhiều khác biệt về hiệu suất.

+0

+1 bởi vì nó sẽ hoạt động. 'StripMultipleChar' có thể được đơn giản hóa một chút. –

+0

nó có thể được đơn giản hóa * và * tối ưu hóa *. Bạn đã có rất nhiều * trong khi * vòng trong đó nó làm cho quay đầu của tôi: tất cả bạn cần là một, thẳng về phía trước cho vòng lặp. –

+0

@Cosmin Prund, Xem bản chỉnh sửa của tôi.chức năng cũ thực sự dựa trên một trong những đơn vị JCL ... – kobik

Các vấn đề liên quan