Chromium

вторник, 26 августа 2014 06:25:29, написал Admin

Chromium – это компонент браузера для Delphi, основанный на движке Chrome. Собственно, в этом и есть его главное преимущество перед стандартным WebBrowser (который основывается на IE).
Другое преимущество Chromium – это удобная работа с куками, что незаменимо при работе с социальными сетями. Может, и WebBrowser тоже такое умеет, но даже не стал глубоко копать – т.к. IE – это абсолютное зло)

В этой статье речь пойдет о Chromium под Delphi 7. В принципе теоретически он наверное встанет и под Lazarus, особенно старая версия: https://code.google.com/p/delphichromiumembedded/

Установка

Идем за самой свежей версией: https://code.google.com/p/dcef3/

Качаем себе на комп, распаковываем сюда: c:\Program Files (x86)\Borland\Delphi7\Lib\dcef3\

Копируем все файлы исходников из c:\Program Files (x86)\Borland\Delphi7\Lib\dcef3\src в c:\Program Files (x86)\Borland\Delphi7\Lib

Открываем через Delphi 7 пакет  c:\Program Files (x86)\Borland\Delphi7\Lib\dcef3\packages\DCEF_D7.dpk

Делаем компиляцию, инсталлируем.

Теперь в конце списка вкладок должна появиться новая вкладка  Chromium.

Закрываем пакет, изменения не сохраняем, перезапускаем Delphi.

Работа с компонентом

Куки

Создадим новый проект, назовем его допустим DelphiBrowser.

Давайте попробуем загрузить страничку ВК.

На форме размещаем компонент TChromium  и кнопку TBitBtn, вешаем событие на кнопку

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  CookieManager: ICefCookieManager;
  CookiesPath : String;
begin
  CookiesPath := ExtractFilePath(Application.ExeName) + ' Cookies/User1';
  CookieManager := TCefCookieManagerRef.Global;
  CookieManager.SetStoragePath(CookiesPath, TRUE );
  Chromium1.Load('http://vk.com/');
end;

В uses проверяем, чтобы был подключен модуль ceflib

В папку с проектом метаем содержимое из c:\Program Files (x86)\Borland\Delphi7\Lib\dcef3\bin\Win32\

Создаем папку Cookies, в ней подпапку User1. Здесь будут лежать куки первого пользователя. Можно создать папку User2 и т.д. и потом переключаться между ними.

Сохраняем изменения и запускаем прогу.

Если все сделано правильно, то при клике на кнопку загрузиться ВК. Войдите под своим логином на сайт, закройте программу. Запустите её снова, нажмите на кнопку. Вы должны оказаться под своим логином, т.е. куки сработали.

Адресная строка

Давайте теперь добавим «адресную строку». Возьмите компонент TLabeledEdit, в заголовок вбейте «Адрес». Поместите вторую кнопку TBitBtn, и повесьте не неё такой обработчик:

procedure TForm1.BitBtn2Click (Sender: TObject);
begin
  Chromium1.Load(LabeledEdit1.Text);
end;

Теперь, если мы вобьем в поле адрес и нажмем на кнопку, то произойдет загрузка нужной страницы.

Давайте чуть усложним задачу. Пусть при переходе по ссылкам значение адреса в поле синхронно изменяется.

Выделяем Chromium1 на форме, жмем F11 (вызов Инспектора), переходим на вкладку Events и дважды кликаем на OnAddressChange. Добавляем код

procedure TForm1.Chromium1AddressChange(Sender: TObject;
  const browser: ICefBrowser; const frame: ICefFrame; const url: ustring);
begin
  LabeledEdit1.Text:=url;
end;

Все, теперь при переходе на другую страницу из браузера её адрес отобразиться в поле.

Скрипты

Теперь рассмотрим как подгружать код JavaScript.

Добавим третью кнопку и прицепим к ней такой обработчик:

procedure TForm1.BitBtn3Click(Sender: TObject);
var
  code: ustring; 
begin
if (Chromium1.Browser.GetMainFrame<>nil) then
  begin
  code:='alert("Hello!");';
  Chromium1.Browser.GetMainFrame.ExecuteJavaScript(code,'',0);
  end
  else ShowMessage('FatalError');
end; 

GetMainFrame проверяет, загружена ли страница. GetMainFrame.ExecuteJavaScript выполняет код JS, в данном случае выводит "Hello!". Но понятно что через JS мы можем манипулировать деревом DOM, совершать различные действия (вбивать в поля данные, кликать по кнопкам, получать значения).

Консоль

Давайте теперь зацепим консоль.

Добавим на форму компонент TMemo.

Повесим обработчик в Chromium на OnConsoleMessage, напишем там такой код:

procedure TForm1.Chromium1ConsoleMessage(Sender: TObject;
  const browser: ICefBrowser; const message, source: ustring;
  line: Integer; out Result: Boolean);
begin
  Memo1.Lines.Add(message);
end;

Исходный код страницы

Давайте получим весь html код страницы.

Добавим на форму еще один компонент TMemo.

Повесим обработчик в Chromium на OnLoadEnd, напишем там такой код:

procedure TForm1.Chromium1LoadEnd(Sender: TObject;
  const browser: ICefBrowser; const frame: ICefFrame;
  httpStatusCode: Integer);
begin
 if (frame <> nil) and frame.IsMain  then
 begin
    Memo1.Lines.Add('Загрузка страницы завершена!'); // для вывода в консоль
    frame.GetSourceProc(callback);
  end;
end;

procedure callback(const str: ustring);
begin
  Form1.Memo2.Lines.Clear; // очищаем Memo
  Form1.Memo2.Lines.Add(str);
  Form1.Memo2.Lines.Add('------------end-frame--------------');
  Application.ProcessMessages;
end;

Блокируем ресурсы

Допустим мы не хотим видет какую-то рекламу. Как заблокировать загрузку ресурса по адресу? Очень просто:

Повесим обработчик в Chromium на OnBeforeResourceLoad, напишем там такой код:

procedure TForm1.Chromium1BeforeResourceLoad(Sender: TObject;
  const browser: ICefBrowser; const frame: ICefFrame;
  const request: ICefRequest; out Result: Boolean);
var
  url: String;
  pos: Integer;
begin
  Result := False; //по умолчанию разрешаем загрузку ресурса (страницы, изображения, видео...)
  url:=request.GetUrl; //получаем текущий урл
  pos:=PosEx('youtube.com', url); //ищем вхождение слова "youtube.com" в урл
  if pos>0 then //если слово содержиться, то
  begin
    Result := True; //запрещаем его загрузку. Таким образом я избавился от лишнего мусора...
  end;  
end;

Настройка прокси

Обнаружилась одна неприятная особенность: своего прокси у Chromium нет. Вообще нет и похоже не предвидеться. Глянул браузеры Google Chrome и Opera - все они используют настройки прокси от системы (т.е. IE). Только Mozilla Firefox продолжает использовать собственные настройки. После долгих часов поиска понял, что похоже единственное решение - подмена каким-то образом системных настроек. Но как конкретно это сделать - не нашел, встречал только упоминания. Буду благодарен, если в комментариях оставите ссылки. Ну а сейчас единственный рабочий вариант - это прописывать параметры прокси в командной строке:

  test.exe --proxy-server=255.255.0.1:80

Соотвественно чтобы программно менять прокси - нужно создать две программы - одна вызывает другую с нужными параметрами...

В параметрах командной строки также можно сменить user-agent:

  test.exe --user-agent="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en)"

Еще исследуются…

Собственно, на этом и закончились мои успехи. Непонятно, как получать данные из DOM? Чтобы они были доступны не только скрипту, но и самой проге. Конечно, получив исходный код страницы можно распарсить его, но во-первых, это не универсальное решение, а во-вторых - динамически подгружаемый контент по-прежнему остается недоступным... Как получить всю DOM модель документа в любой момент времени с помощью самого компонента – увы, не разобрался. Т.е. пока что реальная польза от программы – это заполнение полей своими данными, а до полноценного парсера она не дотягивает….  

 CEF4

Статья устарела, используйте CEF4 https://github.com/salvadordf/CEF4Delphi и вот краткая инструкция

Chromium Delphi Delphi
  

Поделиться статьей с друзьями:

  

Комментарии к статье