Добрый день уважаемые читатели.
На повестке моего дня стоит поиск работы, и для этого я традиционно пользуюсь сайтом www.hh.ru .
На данном сайте размещаются резюме людей, ищущих работу. Сайт очень популярен в среде IT специалистов и можно смело сказать, что в другие места ходить не придется – все работодатели уже здесь.
Сайт устроен по принципу работы с обеих сторон. Если работнику очень нравится вакансия в определенной компании, то он может откликнуться на неё, если работодателю понравилось резюме работника, то он может откликнуться на его резюме.
Работодатель получает список резюме по запросу. Список формируется в зависимости от даты размещения каждого резюме, поэтому важно обновлять дату размещения своего резюме.
Для этого существует специальная кнопка «Обновить дату»
Обновлять резюме можно каждые 4 часа, т.е. 6 раз за сутки.
У сайта есть свой мобильный клиент для Андроида, но скачав его, я не нашел функции, из-за которой я его устанавливал, а именно – «Обновить дату».
Если компания по своим причинам (авто-обновление платное) не делает такой функционал для меня, тогда я сам сделаю его.
В данной статье я хочу поделиться опытом создания программы для сайта www.hh.ru .
Разрабатывать данную программу мы будем на языке Delphi в среде XE5.
Для начала нам нужно провести анализ поведения сайта: что он принимает-отправляет во время нашей с ним работы. Для этих целей в Firefox есть встроенный инструмент Веб-консоль (Инструменты – Веб разработка – Веб-консоль). Методом научного тыка (реверс инженеринга), совместно с товарищем [AltaVista] было выяснено, что браузер посылает POST-запрос с ID резюме по адресу http://hh.ru/applicant/resumes/touch , причем в куках у него должно обязательно лежать 3 параметра :
1) hhtoken – дается при авторизации;
2) hhuid – какое-то ID (по идеи ID человека, разместившего резюме);
3) referrer _id страничка, с которой перешли.
Эти параметры можно увидеть в Веб-консоли после нажатия кнопки «Обновить дату».
Выделяем наш POST запрос.
Переходим во вкладку Куки.
Три параметра мы получили, теперь найдем ID нужного нам резюме.
Оно находится в адресной строке страницы http://hh.ru/resume/6d000db0ff00d00e000000ed1f700000000f51, т.е. нужное нам значение –
ID = 6d000db0ff00d00e000000ed1f700000000f51
Теперь осталось только написать программу, которая с периодичностью 1 раз в 4 часа отправляла бы POST запрос на разведанный адрес.
Для разработки возьмем старый добрый Delphi в его последнем издании XE5.
Давайте опишем создание программы по пунктам:
- Создайте новый проект: File-New-VCL Forms Application
-
Измените в объектном инспекторе свойство формы Caption на «HH bot v2», Color на «clWhite», Position на «poDesktopCenter», BorderStyle на «bsSingle».
- Сохраните файл как Main.pas и проект как hh_bot_v2.dproj, последовательность действий File->Save Project As-> создать отдельную папку для проекта->Unit1.pas заменить на Main.pas-> Project1.dpr заменить на hh_bot_v2.dproj.
- Добавьте на форму компоненты ApplicationEvents,Timer, PopupMenu, TrayIcon, IdHTTP, label-4шт., Edit -4шт, Button, BitButton-2 шт.
Настройте все визуально, чтобы в итоге получилось как на картинке :
- Компоненты Edit последовательно переименуйте в ID_Edit ,hhtoken_Edit, hhuid_Edit.Text, referrer_id_Edit
-
У компонента TrayIcon1 установите свойство PopupMenu на «PopupMenu1», в свойство Hint напишите «Обновление резюме работает», добавьте 2 пункта в это меню :
Данное меню будет показываться при клике правой кнопкой мыши по значку программы в системном трее.
Напишите обработчики кликов данных пунктов:
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.N1Click(Sender: TObject);begin
About_Form.Showmodal;
end;
procedure TForm1.N2Click(Sender: TObject);
begin
Close;
end;
[/cc]
-
Приведите форму к подобному виду:
В нашей программе будет возможность сохранять настройки. Для этого мы будем использовать ini файл.
Изучив документацию, для этих целей выберем не привычный класс TiniFile, а TMemIniFile , потому как Ембаркадеро советует :
«On Windows, a related object, TMemIniFile, works the same way as TIniFile, but the buffer writes in memory to minimize disk access.»
При старте программы сохраненные настройки резюме будут заполнять поля формы. В случае, если настройки изменились, нужно нажать кнопку «Сохранить настройки» и настройки в ini файле обновятся.
Вот заполнение настройками полей во время создания формы:
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.FormCreate(Sender: TObject);
begin
IniFile := TMemIniFile.Create(ChangeFileExt(Application.Exename, ‘.ini’));
{ Вызываем конструктор, в который передаем путь к нашему INI файлу,
в данном случае он будет находится там же где и программа и будет иметь тоже имя файла }
try
ID_Edit.Text := IniFile.ReadString(‘settings’, ‘ID’, ”);
hhtoken_Edit.Text := IniFile.ReadString(‘settings’, ‘hhtoken’, ”);
hhuid_Edit.Text := IniFile.ReadString(‘settings’, ‘hhuid’, ”);
referer_id_Edit.Text := IniFile.ReadString(‘settings’, ‘referer_id’, ”);
finally
end;
end;
[/cc]
Вот процедура Сохранения настроек:
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.Save_BitBtnClick(Sender: TObject);
begin
try
IniFile.WriteString(‘settings’, ‘ID’, ID_Edit.Text);
IniFile.WriteString(‘settings’, ‘hhtoken’, hhtoken_Edit.Text);
IniFile.WriteString(‘settings’, ‘hhuid’, hhuid_Edit.Text);
IniFile.WriteString(‘settings’, ‘referer_id’, referer_id_Edit.Text);
finally
IniFile.UpdateFile; { Обновляем значения в INI файле }
end;
end;
[/cc]
При закрытии программы очищаем созданный класс TMemIniFile
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
try
IniFile.Free; { Освобождаем память }
finally
end;
end;
[/cc]
Теперь напишем процедуру отправки POST-запроса :
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.Refresh_hh(sHHTOKEN: string; sHHUID: string; sREFERID: string;
sResumeID: string);
var
PD: TStringList;
begin
IdHTTP1.Request.ContentType := ‘application/x-www-form-urlencoded’;
IdHTTP1.Request.CustomHeaders.Clear;
IdHTTP1.Request.CustomHeaders.Add(‘Cookie:’ + ‘hhtoken=’ + sHHTOKEN + ‘; ‘ +
‘hhuid=’ + sHHUID + ‘; ‘ + ‘referer_id=’ + sREFERID + ‘; ‘ +
‘dont_redirect=1;’);
PD := TStringList.Create;
PD.Add(‘resume=’ + sResumeID);
PD.Add(‘undirectable=true’);
try
IdHTTP1.Post(‘http://hh.ru/applicant/resumes/touch’, PD);
finally
FreeAndNil(PD);
end;
end;
[/cc]
У неё 4 параметра, которые мы уже разузнали ранее.
В процедуре мы укладываем нужные кукисы в компонент IdHTTP1, а позже отправляем из него запрос с ID резюме по адресу http://hh.ru/applicant/resumes/touch .
В нашей программе будет существовать возможность, как однократного обновления, так и перевода программы в автоматический режим, когда резюме будет обновляться каждые 4 часа.
Кнопку однократного обновления запрограммируем следующим образом :
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.Button1Click(Sender: TObject);
begin
Refresh_hh(hhtoken_Edit.Text, hhuid_Edit.Text, referer_id_edit.Text, ID_Edit.Text);
end;
[/cc]
Для автоматизации этого процесса установите свойство компонента Timer1 Interval равное 14 400 000 (4*60*60*1000)
И у события onTime пропишите:
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Refresh_hh(hhtoken_Edit.Text, hhuid_Edit.Text, referer_id_edit.Text, ID_Edit.Text);
end;
[/cc]
Теперь давайте настроим включение автообновления. Для этого запрограммируйте кнопку «Включить таймер» следующим образом :
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.Timer_BitBtnClick(Sender: TObject);
begin
if not(Timer1.Enabled) then
begin
BitBtn1.Caption := ‘Выключить таймер’;
BitBtn1.font.Color := clred;
Timer1.Enabled := true;
end
else
begin
BitBtn1.Caption := ‘Включить таймер’;
BitBtn1.font.Color := clgreen;
Timer1.Enabled := false;
end;
end;
[/cc]
Если таймер включен, то программу можно будет свернуть и она появится в системном трее. Для этого у компонента ApplicationEvents1
напишем обработчик события OnMinimize :
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.ApplicationEvents1Minimize(Sender: TObject);
begin
if (Timer1.Enabled) then
begin
Hide();
WindowState := wsMinimized;
TrayIcon1.visible := true;
end;
end;
[/cc]
При одиночном клике на иконку в трее, форма программы восстановится. Для этого у компонента TrayIcon1 напишем обработчик события OnClick :
[cc lang=”delphi” tab_size=”2″ line_numbers=”false” no_links=”false”]
procedure TForm1.TrayIcon1Click(Sender: TObject);
begin
TrayIcon1.visible := false;
Show();
WindowState := wsNormal;
Application.BringToFront();
end;
[/cc]
При клике правой кнопкой мыши, появится меню из двух пунктов, при наведении мыши, всплывет сообщение «Обновление резюме работает».
Вот и вся программа. Надеюсь, она поможет вам найти хорошую работу.
Заметил в приведенном коде несколько конструкций вида:
try
IniFile.Free; { Освобождаем память }
finally
end;
Причем в finally – ничего не делается. Вы не могли бы прояснить смысл блока try..finally с пустым finally?
Прояснить могу, программа собиралась из нескольких блоков и это кусок кода из другой программы. Тут и блок try..finally применен не правильно и скорее всего он не нужен вообще, т.к. при IniFile.Free ошибки быть не должно. Если я ошибаюсь, то прошу поправить. Как будет свободное время, я код перепишу на более верный.
> Тут и блок try..finally применен не правильно и скорее всего он не нужен вообще
Вот скорее всего – да.
> т.к. при IniFile.Free ошибки быть не должно
А если она и будет – не очень представляю, что можно было бы осмысленного в таком случае написать в finally.