Автор Тема: Разработка скриптов  (Прочитано 14058 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн nostra

  • Администратор
  • *****
  • Сообщений: 2749
    • Personal Video Database
Разработка скриптов
« : 30 Декабря 2007, 01:43:05 »
Информация в этом топике больше не актуальна. Свежая справка по скриптам доступна здесь: http://www.videodb.info/help/hlp_scripting.html

Начиная с версии 0.9.8.11 в PVD появилась возможность создания скриптов на языке Pascal для загрузки информации из интернет.

Скрипты были добавлены наряду с плагинами, чтобы упростить расширение возможностей программы самими пользователями без глубоких познаний языков программирования.

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

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


Скрипты - это файлы с расширением .psf, находящиеся в папке Scripts. Все скрипты общаются с основной программой с помощью специального движка, который реализован в виде плагина scriptint.dll.
Если этот плагин отсутсвует, то скрипты работать не будут.

Программа встраивает скрипты так, что они по ф-циональности ничем не отличаются от плагинов т.е. их можно настраивать комбинировать и устанавливать по умолчанию.

С помощью скриптов можно загружать:
  • Все информационные поля фильмов, включая пользовательские
  • Все информационные поля персон
  • Постеры

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


Теперь приступим к созданию скрипта...
« Последнее редактирование: 23 Апреля 2010, 12:37:37 от nostra »
Мы уже работаем над постановлением по углублению конструктивных мер, принятых в результате консолидации

Оффлайн nostra

  • Администратор
  • *****
  • Сообщений: 2749
    • Personal Video Database
Re: Разработка скриптов
« Ответ #1 : 12 Июня 2008, 00:39:39 »
1.

Откройте в папку Scripts и сделайте копию любого готового скрипта изменив имя файла на то, которые Вы считаете подходящим.

2.

Откройте файл скрипта в текстовом редакторе (любом, я рекомендую Notepad++)


3. Константы

В начале файла находятся описания типов и ф-ций "встроенных" в движок, которые можно использовать для разбора HTML страниц. Эта часть файла - простой комментарий и совершенно необязательна.

Затем идут объявления констант для удобства работы со скриптом. Эти константы тоже не обязательны, но используя их код будет более читабельным. Перед объявлением констант всегда должен быть оператор const

Константы после строчки //Script data - это описание скрипта и их стоит заполнить:
SCRIPT_VERSIONВерсия плагина
SCRIPT_NAMEНазвание плагина (короткое)
SCRIPT_DESCОписание плагина (длинное)
SCRIPT_LANGЯзык получаемой информации. Пример: $09 - английский, $19 - Русский, $07 - Немецкий. Полный список тут: http://msdn.microsoft.com/en-us/library/ms776294(VS.85).aspx (из этого списка нужно брать число после 0x из колонки "Prim. lang. identifier"). В принципе это не слишком важно укажите ли Вы тут правильный язык, но это всё же желательно для удобства.
SCRIPT_TYPEТип скрипта:
  • получение информации о фильме (константа stMovies)
  • получение информации о персоне (константа stPeople)
  • получение постера (константа stPoster)
BASE_URLДомен первого уровня веб-сайта. Пример: http://www.amazon.com
RATING_NAMEНазвание рейтинга без слова "рейтинг"
SEARCH_STRURL используемый для поиска на веб-сайте. %s заменяется названием фильма/именем персоны
CODE_PAGEКодировка веб-сайта. На пример для windows-1251 значение этой константы равно 1251. Кодировку можно найти в начале страниц HTML, обычно это что-то вроде этого: <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>. Если Вы не знаете, что тут указать введите 0. Полный список значений можно найти тут: http://msdn.microsoft.com/en-us/library/ms776446.aspx

Вы можете объявить так же какие-то свои константы. (На пример для организации настроек скрипта).


4. Глобальные переменные

После строчки //Global variables находятся глобальные переменные. Глобальные переменные могут хранить любую меняющуюся информация, которая должна быть доступна в любом месте скрипта. Глобальным переменным как и локальным (доступным только в определённой ф-ции) всегда предшествует оператор var

В принципе объявлять какие-либо глобальные переменные не обязательно, но я рекомендую создать хотя бы переменную хранящую текущий режим работы скрипта (поиск, парсинг данных). В моих скриптах эта переменная всегда объявлена так: Mode : Byte;
« Последнее редактирование: 16 Июня 2008, 14:29:58 от nostra »
Мы уже работаем над постановлением по углублению конструктивных мер, принятых в результате консолидации

Оффлайн nostra

  • Администратор
  • *****
  • Сообщений: 2749
    • Personal Video Database
Re: Разработка скриптов
« Ответ #2 : 12 Июня 2008, 23:38:05 »
5. Обязательные ф-ции

После того как Вы разобрались с константами и глобальными переменными можно начинать писать сам код. Для обеспечения коммуникации скрипта с движком нужно обязательно написать определённый набор ф-ци:

function GetScriptVersion : WideString;Передаёт версию скрипта
function GetScriptName : WideString;Передаёт название скрипта
function GetScriptDesc : WideString;Передаёт описание скрипта
function GetBaseURL : String;Передёат базовый URL ресурса
function GetScriptLang: Cardinal;Передаёт язык получаемых данных
function GetScriptType : Byte;Передаёт тип скрипта
function GetCurrentMode : Byte;Передаёт текущий режим работы скрипта:
  • Поиск фильма/персона (константа smSearch)
  • Получение данные (любое значение больше 0)
function GetDownloadURL : String;Передаёт URL, который нужно загрузить. В режиме поиска фильма/персоны ф-ция должна возвращать SEARCH_STR
function ParsePage(HTML : WideString; URL : String) : Cardinal;Самая интересная ф-ция в скриптах! :) В переменной HTML содержится код HTML загруженой веб страницы, в переменной URL путь к этой странице. Основная Ваша задача состоит в обработке этих данных.


6. Необязательные ф-ции:

function GetRatingName : WideString;Передаёт название рейтинга
function GetCodePage : Cardinal;Передаёт кодировку скрипта
procedure GetLoginInfo(out URL : String; out Params : String);Передаёт данные для входа в аккаунт пользователя на используемом веб-сайте. Переменной URL должен быть присвоен путь к скрипту регистрации. Переменной Params параметры, которые нужно передать скрипту регистрации. (используется метод POST)

Если Вы используете уже готовый скрипт в качестве шаблона, то Вам скорее всего не нужно будет изменять обязательные ф-ции за исключением ф-ции function ParsePage(HTML : WideString; URL : String) : Cardinal; и может быть ф-ции function GetDownloadURL : String;
« Последнее редактирование: 16 Июня 2008, 14:48:21 от nostra »
Мы уже работаем над постановлением по углублению конструктивных мер, принятых в результате консолидации

Оффлайн nostra

  • Администратор
  • *****
  • Сообщений: 2749
    • Personal Video Database
Re: Разработка скриптов
« Ответ #3 : 13 Июня 2008, 00:30:26 »
7. function GetDownloadURL : String;


В том случае если Ваш скрипт должен только найти фильм/персону и обработать затем только одну страницу с данными, то в этой ф-ции Вам достаточно будет написать вот такой код:

Result := SEARCH_STR

Если нужные данные разбросаны по нескольким страницам, то я рекомендую создать глобальную переменную для дополнительной страницы. Код для 2х страниц будет выглядеть так:

   
 if CreditsURL = '' then
  Result := SEARCH_STR
 else
  Result := SecondPageURL;


Если страниц больше 2х, то можно как дополнительный флаг использовать переменную Mode. На пример вот так (3 страницы):


 if (Mode > smNormal) AND (PosterURL <> '') then
  Result := PosterURL
 else
 if CreditsURL <> '' then
  Result := CreditsURL
 else
  Result := SEARCH_STR;



Если Вы загружаете постер в скрипте сбора информации о фильме или фото в скрипте сбора информации по персоне, то ссылку на изображение нужно передавать в самую последнюю очередь!
« Последнее редактирование: 14 Июня 2008, 17:56:12 от nostra »
Мы уже работаем над постановлением по углублению конструктивных мер, принятых в результате консолидации

Оффлайн nostra

  • Администратор
  • *****
  • Сообщений: 2749
    • Personal Video Database
Re: Разработка скриптов
« Ответ #4 : 13 Июня 2008, 00:33:39 »
8. function ParsePage(HTML : WideString; URL : String) : Cardinal;


Теперь самое главное - парсинг HTML.

В этой ф-ции Вам нужно сделать следующее:
  • а. Определить что это за страница (с результатом поиска / данными по фильму/персоны)
  • б. Установить переменную Mode в соответствующий режим (если он изменился)
  • в. Обработать данные на странице
  • г. Вернуть результат работы ф-ции

а. Определить что это за страница

Это достаточно просто: нужно найти в коде HTML уникальный "маркер" для каждого типа страницы и искать его по нахождении произведя нужные действия. На пример:
if Pos('<title>Фильм</title>', HTML) > 0 then begin

Затем...
б. Установить переменную Mode в соответствующий режим
Mode := smNormal;

Затем...
в. Обработать данные на странице
ParseMovie(URL, HTML); //Это вспомогательная процедура. Просто чтобы разделить код для лучшей читабельности

Затем...
г. Вернуть результат работы ф-ции
Result := prFinished; //скрипт закончил работу

В конце концов часть кода отвечающая за определение страницы с данными о фильме и произведении обязательных действий будет выглядеть так:

if Pos('<title>Фильм</title>', HTML) > 0 then begin
 Mode := smNormal;
 ParseMovie(URL, HTML); //Это вспомогательная процедура. Просто чтобы разделить код для лучшей читабельности
 Result := prFinished; //скрипт закончил работу
end;


Я рекомендую создать для каждой страницы отдельную процедуру такую как ParseMovie(URL, HTML); в примере т.е. скажем:
procedure ParseSearchResults(HTML : WideString); //парсинг результатов поиска
procedure ParseMovie(MovieURL : WideString; HTML : WideString); //парсинг основной информации о фильме
procedure ParseCredits(HTML : WideString); //парсинг доп. страницы с создателями фильма

Пример полного кода ф-ции ParsePage:
function ParsePage(HTML : WideString; URL : String) : Cardinal;
begin
 if Pos('<title>Поиск по сайту</title>', HTML) > 0 then begin
  ParseSearchResults(HTML);
  Result := prList;
//получен список фильмов/персон
end else
 if Pos('Ничего не найдено по запросу', HTML) > 0 then
  Result := prError
//произошла ошибка (фильм не найден)
else
 if (Pos('<title>Фильм</title>', HTML) > 0) then begin
  Mode := smNormal;
  ParseMovie(URL, HTML);
  Result := prFinished;
//скрипт закончил работу
end else
  Result := prError;
//произошла ошибка (не верная страница)
end;
« Последнее редактирование: 16 Июня 2008, 15:10:47 от nostra »
Мы уже работаем над постановлением по углублению конструктивных мер, принятых в результате консолидации

Оффлайн nostra

  • Администратор
  • *****
  • Сообщений: 2749
    • Personal Video Database
Re: Разработка скриптов
« Ответ #5 : 14 Июня 2008, 01:21:37 »
9. Встроенные ф-ции для парсинга


function Pos(Substr : WideString; Str: WideString): Integer
Определяет позицию подстроки SubStr в тексте Str


function PosFrom(const SubStr, Str : WideString; FromIndex : Integer) : Integer
Определяет позицию подстроки SubStr в тексте Str начиная поиск с позиции FromIndex


function LastPos(const SubStr, Str : WideString) : Integer
Определяет позицию подстроки SubStr в тексте Str с конца текста.


function PrevPos(const SubStr, Str : WideString; APos : Integer) : Integer
Определяет позицию подстроки SubStr в тексте Str перед APos.


function RemoveTags(AText : WideString; doLineBreaks : Boolean) : WideString
Удаляет теги из текста AText. На пример: <a href="http://test.com">Test</a> будет преобразован в Test. Если doLineBreaks установлен в True, то тег <br> будет конвертироваться в перевод строки.


function ExplodeString(AText : WideString; var Items : TWideArray; Delimiters : WideString) : Integer
Разделяет сроку AText на подстроки используя разделители Delimiters. Результат пишется в динамический массив Items.


function Copy(S: WideString; Index, Count: Integer): WideString
Копирует Count символов из строки S начиная с Index


procedure Delete(var S: WideString; Index, Count: Integer)
Удаляет Count символов из строки S начиная с Index


procedure Insert(Source: WideString; var Dest: WideString; Index: Integer)
Вставляет строку Source в строку Dest на позиции Index


function Length(S: WideString): Integer
Определяет длину строки S


function Trim(S: WideString): WideString
Убирает невидимые символы (пробел, перевод строки, абзац) из строки S


function CompareText(S1, S2: WideString): Integer
Сравнивает 2 строки (S1 и S2) без учёта регистра. Возвращает 0 если строки равны, значение > 0 если S1 > S2 и значение < 0 если S1 < S2.


function CompareStr(S1, S2: WideString): Integer
Сравнивает 2 строки (S1 и S2) с учётом регистра. Возвращает 0 если строки равны, значение > 0 если S1 > S2 и значение < 0 если S1 < S2.


function UpperCase(S: WideString): WideString
Переводит все символы в строке S в верхний регистр (большие буквы).


function LowerCase(S: WideString): WideString
Переводит все символы в строке S в нижний регистр (маленькие буквы).


function StringReplace(S, OldPattern, NewPattern: WideString; ReplaceAll : Boolean; IgnoreCase : Boolean; WholeWord: Boolean): WideString 
Заменяет OldPatter на NewPattern в строке S. Если ReplaceAll установлен в True, то заменяются все повторения OldPattern. Если IgnoreCase установлен в True, то сравнение подстрок ведётся без учёта регистра.


function StrToInt(const S: WideString): Integer
Преобразовывает строку в целое число


function IntToStr(const Value: Integer): WideString
Преобразовывает целое число в строку


function StrToFloat(const S: WideString): Extended
Преобразовывает строку в действительное число


  function FloatToStr(const Value: Extended): WideString
Преобразовывает действительное число в строку


function HTMLValues(const HTML : WideString; ABegin, AEnd, ItemBegin, ItemEnd : WideString; ValDelim : WideString; var Pos : Integer) : WideString
Собирает значения из HTML в строку разделяя их разделителем ValDelim. Ф-ция ищет сначала подстроку ABegin начиная с позиции Pos, начиная с неё выбирает значения между подстроками ItemBegin и ItemEnd пока не встретится AEnd. Конечная позиция в тексте возвращается в переменную Pos.


function HTMLValues2(const HTML : WideString; ABegin, AEnd, ItemBegin, ItemEnd : WideString; ValDelim : WideString; var Pos : Integer) : WideString
Аналогично HTMLValues, но после ItemBegin ищется конец тега > и значение читается после него.


function TextBetween(const HTML : WideString; ABegin, AEnd : WideString; doLineBreaks : Boolean; var Pos : Integer) : WideString
Возвращает текст без HTML тегов из строки HTML, начиная с ABegin и заканчивая AEnd. ABegin ищется начиная с позиции Pos.


function HTMLToText(const HTML : WideString) : WideString
Преобразует все значения символов используемые в HTML для таких символов как <, >, $, " и т.д. в текст
Мы уже работаем над постановлением по углублению конструктивных мер, принятых в результате консолидации

Оффлайн nostra

  • Администратор
  • *****
  • Сообщений: 2749
    • Personal Video Database
Re: Разработка скриптов
« Ответ #6 : 14 Июня 2008, 01:41:04 »
10. Ф-ции заполнения полей (наконец-то :) )



10.1. Ф-ции для заполнения стандартных (для плагинов загрузки информации) полей


procedure AddSearchResult(Title1, Title2, Year, URL, PreviewURL : WideString)
Добавляет результат поиска. Все переменные заполнять не обязательно, главное заполнить хотя бы Title1 или Title2 и URL.


procedure AddFieldValue(AField: Integer; AValue : WideString)
Добавляет значение поля (AValue). AField может принимать следующие значения:
Для фильмов:
0URL
1Название
2Ориг. название
3Другие названия
4Год
5Жанр
6Категория
7Страна
8Студии
9MPAA
10Доп. рейниг
11Теги
12Слоган
13Описание
14Длительность
15Бонусы

Для персон:
0URL
1Имя
2Переведённое имя
3Другие имена
4Дата рождения
5Место рождения
6Жанр
7Биография
8Дата смерти


procedure AddMoviePerson(Name, TransName, Role, URL : WideString; AType : Byte)
Добавляет участника фильма. AType может принимать следующие значения:
0Актёр
1Режиссёр
2Сценарист
3Композитор
4Продюсер


procedure AddPersonMovie(Title, OrigTitle, Role, Year, URL : WideString; AType : Byte)
Добавляет фильм в фильмографию. AType может принимать следующие значения:
0Актёр
1Режиссёр
2Сценарист
3Композитор
4Продюсер


procedure AddAward(Event, Award, Category, Recipient, Year: WideString; const Won : Boolean)
procedure AddAwardEx(Event, Award, Category, RecipientVal1, RecipientVal2, Year: String; const Won : Boolean)
Добавляет награду.


procedure AddConnection(Title, OrigTitle, Category, URL, Year: WideString)
Добавляет связь с другим фильмом.


procedure AddEpisode(Title, OrigTitle, Description, URL, Year, Season, Episode : WideString)
Добавляет эпизод.


10.2. Ф-ции для остальных полей


procedure AddFieldValueXML(AField: WideString; AValue : WideString)
Эту ф-цию можно использовать для полей которые нельзя заполнить ф-циями указаными выше (за исключением пользовательских полей). Стандартные поля тоже можно заполнять с её помощью.
В переменной AValue передаётся значение поля, а AField - это строка(название) соответствующая определённому полю:

Для фильмов:
num
title
origtitle
aka
year
genre
country
studio
release
mpaa
location
category
tagline
description
count
type
rating
imdbrating
orating
orname
rip
length
langs
translation
resolution
videocodec
videobitrate
audiocodec
audiobitrate
size
url
path
comment
dateadded
code
label
loan
subs
framerate
label
features
viewed
bookmark
wish
loandate
viewdate
tags


Для персон:
name
transname
altnames
birthday
birthplace
bio
death



procedure AddCustomFieldValueByNumber(CustomNumber: Integer; AValue : WideString)
Заполняет пользовательское поле по порядковому номеру поля.
CustomNumber - номер пользовательского поля по счёту
AValue - значение (используйте '-1' для True(галочка установлена) и '0' для False)


procedure AddCustomFieldValueByName(CustomName: WideString; AValue : WideString)
Заполняет пользовательское поле названию поля.
CustomName - название пользовательского поля
AValue - значение
« Последнее редактирование: 11 Февраля 2010, 05:41:44 от Reset »
Мы уже работаем над постановлением по углублению конструктивных мер, принятых в результате консолидации

Оффлайн nostra

  • Администратор
  • *****
  • Сообщений: 2749
    • Personal Video Database
Re: Разработка скриптов
« Ответ #7 : 14 Июня 2008, 02:39:20 »
11. Другие ф-ции


procedure ShowMessage(const Msg, Head : WideString)
Выводит текстовое сообщение с кнопкой OK.
Head - Название окна
Msg - Текст сообщения


12. Проверка работы скрипта


После того как Вы написали скрипт нужно проверить его работоспособность. Для этого запустите PVD с параметром -debug, вот так: viddb.exe -debug
Запустив программу с этим параметром в меню "Помощь" появится меню Log, которое открывает окно с логом программы.
В этом окне можно получить следующую информацию:
  • какие плагины загружает программа
  • какие скрипты компилируются
  • какие ошибки происходят при компилировании скриптов
  • какие веб страницы загружает программа при работе плагина/скрипта

Если скрипт не может быть скомпилирован из-за ошибок, то в программу он не подгружается и соответственно не появляется в меню "Импорт" или в списке плагинов в настройках.

При компиляции скрипта компилятор выводит сообщение при обнаружении ошибки с информацией в каком месте скрита была найдена ошибка и описанием ошибки.
На пример: [Error] (366:2): Semicolon (';') expected
Это означает, что в строке 366 на позиции 2 отсутствует ; (на самом деле она вероятнее всего отсутствует в конце строки 365)

Так же компилятором выводятся подсказки по оптимизации кода.
На пример: [Hint] (368:2): Variable 'TEST' never used
Это означает, что переменная Test объявленная в строке 368 на позиции 2 не была использована.

Если скрипт компилируется, но работает не корректно можно воспользоваться ф-цией ShowMessage для вывода значений переменных в части кода, который не правильно работает, а так же проверить правильность URL-ов загружаемых программой в логе.

В режиме -debug программа так же пишет текст загружаемых страниц в файл page.html в папку программы. (там всегда находится последняя страница загруженная программой).
« Последнее редактирование: 14 Июня 2008, 16:33:27 от nostra »
Мы уже работаем над постановлением по углублению конструктивных мер, принятых в результате консолидации