TWebBrowser中的HTML源代码-如何检测流编码?

4

基于这个问题:如何从TWebBrowser获取HTML源代码

如果我用一个具有Unicode编码的html页面运行这段代码,结果会是乱码,因为D7中的TStringStream不是Unicode。该页面可能是UTF8编码或其他(Ansi)编码。

我该如何检测TStream/IPersistStreamInit是否是Unicode / UTF8 / Ansi?

如何始终返回此函数的正确结果作为 WideString

function GetWebBrowserHTML(const WebBrowser: TWebBrowser): WideString;

如果我使用TMemoryStream代替TStringStream,并将TMemoryStream保存到文件中,那么一切都很好。文件可以是Unicode/UTF8/Ansi编码。但我始终希望将流作为WideString返回:

function GetWebBrowserHTML(const WebBrowser: TWebBrowser): WideString;
var
  // LStream: TStringStream;
  LStream: TMemoryStream;
  Stream : IStream;
  LPersistStreamInit : IPersistStreamInit;
begin
  if not Assigned(WebBrowser.Document) then exit;
  // LStream := TStringStream.Create('');
  LStream := TMemoryStream.Create;
  try
    LPersistStreamInit := WebBrowser.Document as IPersistStreamInit;
    Stream := TStreamAdapter.Create(LStream,soReference);
    LPersistStreamInit.Save(Stream,true);
    // result := LStream.DataString;
    LStream.SaveToFile('c:\test\test.txt'); // test only - file is ok
    Result := ??? // WideString
  finally
    LStream.Free();
  end;
end;

编辑:我找到了这篇文章 - 如何以Delphi方式在 TWebBrowser 中加载和保存文档

这正是我所需要的,但它只能在 Delphi Unicode 编译器(D2009+)中正确工作。请阅读结论部分:

我们可以做更多事情。有一些事情立即浮现出来。我们将Unicode功能和非ANSI编码支持适用于先前的Unicode编译器代码。如果文档字符集不是ANSI,则使用早于 Delphi 2009 的任何编译器编译的当前代码将不能正确地将文档内容保存到字符串中。

魔法显然在于 TEncoding 类(TEncoding.GetBufferEncoding)。但 D7 没有 TEncoding。有什么想法吗?


1
也许这可以帮助你 http://msdn.microsoft.com/zh-cn/library/jj160620(v=vs.85).aspx - Sir Rufo
尝试一些支持Unicode的StringList。jcl.sf.net库有TWideStringListTJclWideStringList,TNT Unicode组件也有TWideStringList,我认为还有更多。也许其中一些还有COM IStringList适配器。无论如何,尝试这些或在Google、torry.net或其他收集器上搜索更多的Delphi 7 Unicode StringList实现。 - Arioch 'The
MSIE引入了.outerHTML和.innerHTML等属性到DOM中。因此,我打赌你需要获取HTML DOM树,获取HTML标记,然后获取其outerHTML属性作为BSTR aka WideString,而不需要中间COM对象。也许你需要一点JavaScript来实现这个。搜索类似“如何在TWebControl中点击按钮”的主题 - 它们将为您提供如何从Delphi侧定位某些标记作为JS对象以及如何调用其方法/属性的示例。您需要读取根HTML标记的outerHTML属性。 - Arioch 'The
1个回答

2

我使用 GpTextStream 来处理转换(适用于所有 Delphi 版本):

function GetCodePageFromHTMLCharSet(Charset: WideString): Word;
const
  WIN_CHARSET = 'windows-';
  ISO_CHARSET = 'iso-';
var
  S: string;
begin
  Result := 0;
  if Charset = 'unicode' then
    Result := CP_UNICODE else
  if Charset = 'utf-8' then
    Result := CP_UTF8 else
  if Pos(WIN_CHARSET, Charset) <> 0 then
  begin
    S := Copy(Charset, Length(WIN_CHARSET) + 1, Maxint);
    Result := StrToIntDef(S, 0);
  end else
  if Pos(ISO_CHARSET, Charset) <> 0 then // ISO-8859 (e.g. iso-8859-1: => 28591)
  begin
    S := Copy(Charset, Length(ISO_CHARSET) + 1, Maxint);
    S := Copy(S, Pos('-', S) + 1, 2);
    if S = '15' then // ISO-8859-15 (Latin 9)
      Result := 28605
    else
      Result := StrToIntDef('2859' + S, 0);
  end;
end;

function GetWebBrowserHTML(WebBrowser: TWebBrowser): WideString;
var
  LStream: TMemoryStream;
  Stream: IStream;
  LPersistStreamInit: IPersistStreamInit;
  TextStream: TGpTextStream;
  Charset: WideString;
  Buf: WideString;
  CodePage: Word;
  N: Integer;
begin
  Result := ''; 
  if not Assigned(WebBrowser.Document) then Exit;
  LStream := TMemoryStream.Create;
  try
    LPersistStreamInit := WebBrowser.Document as IPersistStreamInit;
    Stream := TStreamAdapter.Create(LStream, soReference);
    if Failed(LPersistStreamInit.Save(Stream, True)) then Exit;
    Charset := (WebBrowser.Document as IHTMLDocument2).charset;
    CodePage := GetCodePageFromHTMLCharSet(Charset);
    N := LStream.Size;
    SetLength(Buf, N);
    TextStream := TGpTextStream.Create(LStream, tsaccRead, [], CodePage);
    try
      N := TextStream.Read(Buf[1], N * SizeOf(WideChar)) div SizeOf(WideChar);
      SetLength(Buf, N);
      Result := Buf;
    finally
      TextStream.Free;
    end;
  finally
    LStream.Free();
  end;
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接