【问题标题】:PosEx on a String with more than 1024 Chars超过 1024 个字符的字符串上的 PosEx
【发布时间】:2021-06-16 11:38:11
【问题描述】:

我有一个简单的函数可以从 HTML 的 ​meta property="og:image" 中获取值:

Function HTML_GetOGImage(HTML:String;Var URL:String):Boolean;
Var
  I,A,B,C:Integer;
Begin
  Result:=False;
  A:=PosEx('og:image',HTML,1);
  If A<>0 Then B:=PosEx('content="',HTML,A+9)Else Exit;
  If B<>0 Then C:=PosEx('"',HTML,B+9)Else Exit;
  For I:=B+9 To C-1 Do URL:=URL+HTML[I];
  Result:=True;
End;

它工作得很好,但是在某些网站上,HTML 是一长串没有回车的字符,meta 的位置高于 1024,函数返回,什么都不做。 (即here)。

处理长字符串的最佳做法是什么? PosEx 是否限制了字符串的长度?

【问题讨论】:

  • 如果这是真的,我会说这是一个错误。您使用的是哪个版本的 Delphi?
  • 我发现以下 URL 使用您的确切代码进行扫描:'leparisien.fr/resizer/tHSUGi9wTnVSkXz4NUvbjObFPVw=/1200x675/…'
  • 像@HeartWare 一样,我使用您的 Delphi 版本在您的页面上尝试了您的代码。我得到leparisien.fr/resizer/tHSUGi9wTnVSkXz4NUvbjObFPVw=/1200x675/…
  • (离题提示:不要做For I:=B+9 To C-1 Do URL:=URL+HTML[I];。使用Copy。并使用适当的HTML解析器。)
  • >1024没有问题。正如我所说,我的测试发现它位于 4000+ 位置。无论如何,如果您找到了替代解决方案,那是主要的......

标签: html string delphi delphi-10.3-rio


【解决方案1】:

这不可能是PosEx() 的错。可以通过强制一种您认为是罪魁祸首的情况来简单地对此进行反测试:

var
  s: String;
  i: Integer;
begin
  // Just a long string
  SetLength( s, 2000 );
  for i:= 1 to 2000 do s[i]:= Chr( i mod 10+ $30 );

  // The text to be found is clearly after 1024 characters
  s:= s+ 'og:image';
  i:= PosEx( 'og:image', s, 1 );

  // Should not be 0 but instead 2001
  Writeln( i );

如果此代码适用于您并且找到了搜索文本,那么您的错误就在其他地方。 PosEx()(和Pos())对于更大的字符串(即一百万个字符)也应该没有问题。我认为您的理解是错误的:您希望您的变量 HTML 包含您想要的内容,但您是否检查过它的长度或内容(通过将其保存到文件中)?

【讨论】:

    【解决方案2】:

    PosEx() 完美运行,没有任何问题。你的问题是错误的

    在你的 delphi 中运行它,我没有发现任何问题。

    Unit1.dfm

    object Form1: TForm1
      Left = 0
      Top = 0
      Caption = 'Form1'
      ClientHeight = 231
      ClientWidth = 505
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      OnShow = FormShow
      PixelsPerInch = 96
      TextHeight = 13
      object WebBrowser1: TWebBrowser
        Left = 0
        Top = 0
        Width = 505
        Height = 231
        Align = alClient
        TabOrder = 0
        OnDownloadComplete = WebBrowser1DownloadComplete
        ExplicitLeft = 120
        ExplicitTop = 73
        ExplicitWidth = 300
        ExplicitHeight = 150
        ControlData = {
          4C00000031340000E01700000000000000000000000000000000000000000000
          000000004C000000000000000000000001000000E0D057007335CF11AE690800
          2B2E126208000000000000004C0000000114020000000000C000000000000046
          8000000000000000000000000000000000000000000000000000000000000000
          00000000000000000100000000000000000000000000000000000000}
      end
    end
    

    unit1.pas

    unit Unit1;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
          Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.OleCtrls, SHDocVw;
    
    const
      siteURL = 'https://www.leparisien.fr/societe/sante/covid-19-fin-de-la-periode-disolement-de-jean-castex-dont-lepouse-avait-ete-testee-positive-suivez-notre-direct-16-06-2021-BKACFU43MBAATAOLEN7BYHNNIY.php';
    
    type
      TForm1 = class(TForm)
        WebBrowser1: TWebBrowser;
        procedure FormShow(Sender: TObject);
        procedure WebBrowser1DownloadComplete(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    uses System.StrUtils, ActiveX;
    
    function HTML_GetOGImage(HTML:String;var URL:String) : Boolean;
    bar
      I,A,B,C:Integer;
    begin
      Result:=False;
      A := PosEx('og:image',HTML,1);
      If A<>0 Then B:=PosEx('content="',HTML,A+9)Else Exit;
      If B<>0 Then C:=PosEx('"',HTML,B+9)Else Exit;
      URL := Copy(HTML, B+9, C-B-9); //I prefer <- instead of -> For I:=B+9 To C-1 Do URL:=URL+HTML[I];
    
      ShowMessage('A = ' + IntToStr(A) +#13#10+ 'B = ' + IntToStr(B) +#13#10+ 'C = ' + IntToStr(C)); //remove this line after test
      Result := True;
    end;
    
    procedure TForm1.FormShow(Sender: TObject);
    begin
      WebBrowser1.Navigate(siteURL);
    end;
    
    procedure TForm1.WebBrowser1DownloadComplete(Sender: TObject);
    var
      LStream: TStringStream;
      Stream : IStream;
      LPersistStreamInit : IPersistStreamInit;
      URL : String;
    begin
      if not Assigned(WebBrowser1.Document) then exit;
      LStream := TStringStream.Create('');
      try
        LPersistStreamInit := WebBrowser1.Document as IPersistStreamInit;
        Stream := TStreamAdapter.Create(LStream,soReference);
        LPersistStreamInit.Save(Stream,true);
        HTML_GetOGImage(LStream.DataString, URL);
      finally
        LStream.Free();
      end;
    end;
    
    end.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-03
      • 2021-02-03
      • 1970-01-01
      • 2012-06-18
      相关资源
      最近更新 更多