Как сохранить web страницу в текстовую переменную  (в string)?

Потому, что рассмотренные методы возвращают первоначальный HTML код веб-документа. Но в документе имеются скрипты, AJAX, например (технология фонового взаимодействия с сервером) - они изменяют содержимое веб-документа уже после загрузки первоначального HTML кода. Например, дерево комментариев подгружается скриптами из базы данных, а потом располагается в определённом месте веб-страницы.

Ещё дополню про получение исходного HTML кода страницы.

HTML.body.innerText - это HTML код, который обрамлён тегами <body></body>. HTML.body.outerText - HTML код, который содержится в тегах <body></body>, включая сами эти теги (вместе с атрибутами).

Но HTML код страницы содержит и другие сведения, расположенные за пределами этих тегов. Чтобы получить весь HTML код документа, можно поступить так:

DelphiВыделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

uses
  ActiveX, MSHTML;
 
//(Delphi 7: String = AnsiString.)
//Получить HTML код веб-страницы.
function GetHTMLCode(WebBrowser1: TWebBrowser) : String;
var
  Ss : TStringStream;
begin
  Ss := TStringStream.Create('');
  try
    //Читаем потоковое содержимое веб-документа.
    (WebBrowser1.Document as IPersistStreamInit).Save(TStreamAdapter.Create(Ss), True);
    //Учитываем кодировку текста.
    if (WebBrowser1.Document as IHTMLDocument2).charset = 'utf-8' then
      Result := Utf8ToAnsi(Ss.DataString)
    else
      Result := Ss.DataString;
  finally
    FreeAndNil(Ss);
  end;
end;
 
//Показ HTML кода веб-документа в Memo.
procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text := GetHTMLCode(WebBrowser1);
end;

Более подробно:

DelphiВыделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

uses
  ActiveX, MSHTML;
 
//(Delphi 7: String = AnsiString.)
//Выгрузка потокового содержимого объекта в стоку однобайтных символов.
//В эту строку может быть выгружено любое содержимое - не только текст,
//но и бинарные данные - изображения, звук, видео и пр. В зависимости от типа объекта.
function ObjStreamToStr(const aDisp : IDispatch) : String;
const
  SelfName = 'ObjStreamToStr()';
var
  IPsi : IPersistStreamInit;
  IStr : IStream;
  Ss : TStringStream;
begin
  Result := '';
  //Проверяем, есть ли ссылка на интерфейс объекта.
  if aDisp = nil then
    raise Exception.Create(SelfName + '. Ссылка на интерфейс объекта - пустая!');
  //Проверяем, поддерживает ли объект потоковый интерфейс.
  //Если потоковый интерфейс поддерживается, то подключаемся к нему.
  if aDisp.QueryInterface(IPersistStreamInit, IPsi) <> S_OK then //S_OK = 0
    raise Exception.Create(SelfName + '. Объект не поддерживает потоковый интерфейс!');
 
  //Создаём строковый поток.
  Ss := TStringStream.Create('');
  try
    {Создаём потоковый адаптер и подключаем его к строковому потоку.
    Потоковый адаптер реализует интерфейс IStream.
    Второй параметр задаёт значение свойства TStreamAdapter.StreamOwnership:
      soReference - показывает, что потоковый адаптер не является ответственным за
        уничтожение экземпляра Ss. Т. е., при своём уничтожении потоковый адаптер
        не должен уничтожать связанный с ним поток Ss.
        Значение soReference является предустановленным.
      soOwned - показывает, что потоковый адаптер является ответственным за
        уничтожение экземпляра Ss. Т. е., при своём уничтожении потоковый адаптер
        должен уничтожить поток Ss.}
    IStr := TStreamAdapter.Create(Ss, soReference);
    //Записываем содержимое объекта в строковый поток (через интерфейс IStr).
    IPsi.Save(IStr, True);
    //Получаем данные строкового потока в виде строки.
    Result := Ss.DataString;
  finally
    FreeAndNil(Ss); //Уничтожаем экземпляр Ss.
  end;
  //Экземпляры, связанные с интерфейсами IPsi и IStr будут автоматически
  //уничтожены при обнулении счётчиков ссылок на эти интерфейсы.
  //В данном случае это произойдёт при выходе управления из этой подпрограммы.
end;
 
//Показ HTML кода веб-документа в Memo.
procedure TForm1.Button1Click(Sender: TObject);
var
  S : String;
begin
  //Получаем потоковое содержимое веб-документа в виде строки.
  S := ObjStreamToStr(WebBrowser1.Document);
  //Учитываем кодировку текста.
  if (WebBrowser1.Document as IHTMLDocument2).charset = 'utf-8' then
    Memo1.Text := Utf8ToAnsi(S)
  else
    Memo1.Text := S;
end;

Akmas

, чтобы обработать текущее содержимое страницы, понадобится либо работать с DOM моделью документа, например:

Автозаполнение web ComboBox

.

Либо, надо искать какой-нибудь способ для получения текущего текста веб-страницы (возможно, без HTML тегов).

Добавлено через 1 час 34 минуты

Хотя нет... Те коды, что предложил

cotseec

и я - они текущее состояние обрабатывают - на момент обращения к объектам веб-страницы. В общем, это надо разбираться со страницами на Ютубе.

Сейчас ещё попробовал, используя объект-диапазон, выделить часть документа и прочитать её - всё то же самое - текст комментариев не удалось получить:

DelphiВыделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

procedure TForm1.Button1Click(Sender: TObject);
var
  Body : IHTMLBodyElement;
  TxtRng : IHTMLTxtRange;
begin
  Body := (WebBrowser1.document as IHtmlDocument2).body as IHTMLBodyElement;
  TxtRng := Body.createTextRange as IHTMLTxtRange;
  //Связываем объект-диапазон с элементом <BODY>.
  TxtRng.moveToElementText(Body as IHTMLElement);
  //Выделяем содержимое связанного элемента.
  TxtRng.select;
  //Получаем содержимое связанного элемента.
  Memo1.Text := TxtRng.htmlText; //HTML код.
  Memo2.Text := TxtRng.text; //Текст.
end;