Спецификация API для работы с сервером Антиплагиата

 

Запрос к серверу:

 

Адрес: http://{xxx.xxx.xxx.xxx}:{порт}/etxt_antiplagiat

POST-параметры для различных действий:
 
1) Получение текущего состояния сервера:
 
try=1

2) Постановка пакета в очередь на проверку
 
xmlUrl={Адрес к xml-пакету с текстами на проверку}
xmlAnswerUrl={Адрес к скрипту, принимающего результаты проверки, должен в конце возвращать "ok" латинскими символами (без кавычек)}
 
Примечание:
 
  • пакет успешно поставлен в очередь на проверку, если код ответа сервера Code=1
  • если скрипт, принимающий результаты проверки не будет возвращать в конце "ok", то сервер антиплагиата будет вновь и вновь повторять попытки отправки результатов проверки

 
Ответ сервера (в JSON формате):
 
 
Code - Возвращает код ответа сервера:
 
0 - Неизвестная ошибка
1 - Задача на пакетную обработку принята
3 - Неверно указан (или вообще не указан) адрес к xml-файлу с пакетом документов для обработки
4 - Неверно указан адрес при запросе к серверу (должен быть в форме http://{xxx.xxx.xxx.xxx}:{порт}/etxt_antiplagiat)
5 - Неверно указан (или вообще не указан) адрес к скрипту, принимающего результаты обработки проверки
6 - Запрос на состояние сервера успешно обработан
7 - Отсутствует доступ к Интернет
8 - Принята команда на остановку сервера
9 - Запрос на получение трассировочной информации с сервера успешно обработан
10 - Запрос отклонен из-за невозможности проверить доступ клиента к сервису. Можно повторить попытку немного позже
11 - Запрос отклонен из-за отсутствия доступа к сервису (скорей всего из-за нулевого баланса)
12 - Запрос отклонен из-за превышения макс-го кол-ва пакетов в очереди (50 по умолчанию)
13 - Запрос отклонен из-за истечения срока тестового доступа
 
Description - Возвращает текстовое описание ответа сервера
NumPacketsInQueue - Возвращает текущее число пакетов в очереди
AvgDocumentTime - Возвращает среднее время обработки документа в пакете, в минутах. Будет меньше нуля, если пока эту характеристику невозможно вычислить
CurrentPacketTime - Текущее время обработки текущего пакета, в минутах (целое число).
 
Пример ответа:
 
{"Code":3,"Description":"В запросе отсутствует адрес с пакетом данных для обработки","NumPacketsInQueue":2,"AvgDocumentTime":-1.000000E+000, "CurrentPacketTime":0}
 
 
Получение результата:
 
 
Результат получает скрипт, адрес которого был указан в POST-параметре при запросе к серверу. Ему будут доступны следующие POST-поля:
 
XmlFileName - Имя файла Xml-пакета с документами
NumDocsInPacket - Число документов в пакете
PacketTime - Время обработки пакета, в минутах
DocumentTime - Среднее время обработки документа в пакете, в минутах
ServerType - Параметр, полученный от клиента в Xml-пакете при запросе
TotalWords - Общее число слов всех документов из пакета после канонизации
Xml - Результат проверки Xml-пакета, зашифрованный, а затем и кодированный в Base64
Error - Содержит ошибку, если не удалось проверить Xml-пакет (в этом случае все строковые POST-поля будут пустыми (кроме XmlFileName), а целочисленные - нулевые). Закодирован в Base64
 
 
Формат Xml-пакета (ЗАПРОС)
 
 
Примечания:
 
  • символами [] обозначается опциональность присутствия узлов/атрибутов
 
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <serverType>{Строка}</serverType>
    [<exceptions>
      <url>{Url, игнорируемое при проверке на уникальность каждого документа из пакета, закодированный в Base64}</url>
        ...
      <url>...</url>
      <domain>{домен, игнорируемый при проверке на уникальность каждого документа из пакета, закодированный в Base64}</domain>
        ...
      <domain>...</domain>
    </exceptions>]
    <entry>
        <id>{Число}</id>
        <type>{Строка}</type>
        <uservars>{Любые пользовательские данные в Xml формате}</uservars>
        <name>{Имя текста, закодированное в Base64}</name>
        [<text>{Текст на проверку, закодированный в Base64}</text>]
        [<exceptions>
          <url>{Url, игнорируемое при проверке на уникальность, закодированный в Base64}</url>
            ...
          <url>...</url>
          <domain>{домен, игнорируемый при проверке на уникальность, закодированный в Base64}</domain>
            ...
          <domain>...</domain>
        </exceptions>]
    </entry>
    <entry>
        ...
    </entry>
</root>
 
 
Формат Xml-пакета (ОТВЕТ)
 
 
Примечания:
 
  • символами [...] обозначается опциональность присутствия узлов/атрибутов
  • если уникальность проверенного текста = 100, то поле ftext отсутствует
  • в полях url возвращаются (максимум 5) url страниц с наибольшим процентом совпадений с проверяемым текстом
 
<?xml version="1.0" encoding="UTF-8"?>
 
<root>
  <numPacketsInQueue>{текущее число пакетов в очереди}</numPacketsInQueue>
  [<exceptions>
    <url>{Url, игнорировавшийся при проверке на уникальность каждого документа из пакета, закодированный в Base64}</url>
      ...
    <url>...</url>
    <domain>{домен, игнорировавшийся при проверке на уникальность каждого документа из пакета, закодированный в Base64}</domain>
      ...
    <domain>...</domain>
  </exceptions>]
  <entry>
    <id>{Число}</id>
    <type>{Строка}</type>
    <uservars>{Любые пользовательские данные в Xml формате}</uservars>
    <name>{Имя текста, закодированное в Base64}</name>
    [<ftext uniq={Уникальность текста(целое число)}>
      {Проверенный текст с выделенными совпашими шинглами (в текстовом виде или картинке jpeg), закодированный в Base64}
    </ftext>]
    [<urls>
        <url unique={уникальность проверяемого текста по отношению к содержимому данного url (целое число, от 0 до 100)}
             color={цвет выделения совпавших шинглов в ftext, в виде #xxxxxx}
             [title={содержимое тэга title страницы с данным Url, закодированное в Base64}]>
             {Url, по которому нашлось совпадение с проверяемым текстом, закодированное в Base64}
        </url>
        <url ...> ...</url>
        ...
    </urls>]
    <statistics>
      <download_ratio>{Отношение общего кол-ва скачанных страниц ко всем страницам (в процентах)}</download_ratio>
      <total_pages>{Общее кол-во страниц, которое планировалось закачать}</total_pages>
    </statistics>
    [<exceptions>
      <url>{Url, игнорировавшийся при проверке на уникальность, закодированный в Base64}</url>
        ...
      <url>...</url>
      <domain>{домен, игнорировавшийся при проверке на уникальность, закодированный в Base64}</domain>
        ...
      <domain>...</domain>
    </exceptions>]
  </entry>
  <entry>
    ...
 
  </entry>
  ...
 
</root>
 
 
PHP-класс для общения с сервером Антиплагиата
 
 
<?
 
define('CHECK_KEY', 'ВАШ КЛЮЧ');
 
class EtxtAntiPlagiat
{
    // путь до сервера антиплагиата
    private $serverUrl = array (
        'server' => 'xxx.xxx.xxx.xxx:yyy/etxt_antiplagiat',
    );
 
    // тип сервера по умолчанию
    public $serverType = 'server';
    // путь до веб части проверки
    private $localServer = 'http://www.site.ru/';
    // путь для получения результата
    public $localUrl    = 'http://www.site.ru/antiplagiat/upload.php';
    // массив объектов на проверку
    private $ItemsToCheck = array();
    // папка для xml заданий
    private $xmlPath = '/home/user/site.ru/htdocs/antiplagiat/xml/';
    // типы объектов для проверки
    private $typesObjects = array ('text');
    // ключ использования шифра
    public $useCrypt = 1;
    // флаг соединения с сервером антиплагиата
    public $isConnect = false;
    // статус ошибки
    public $Error = '';
    // флаг-значение приоритета пакета
    public $sort = 0;
    
    // конструктор, параметр - имя xml файла
    function EtxtAntiPlagiat($path = '', $my_crypt = 1, $serverType = 'server')
    {
        if ($path) $this->xmlPath .= $path;
        
        $this->useCrypt = $my_crypt;
 
        if ($this->useCrypt == 1) $this->useCrypt = CHECK_KEY;
 
        $this->serverType = $serverType;
        
        // пингуем сервер
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->serverUrl[$this->serverType]);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "try=1");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        $json = curl_exec($ch);
        curl_close($ch);
 
        // устанавливаем результат пинга
        $this->isConnect = $json ? $json : false;
        $this->isConnect = str_replace('\,', ',', $this->isConnect);
        if (($tmp = json_decode($this->isConnect)) && $tmp->Code == 7) {
            $this->isConnect = false;
            $this->Error = $tmp->Description;
        }
    }
    
    // функция добавления объекта на проверку
    public function addItemToCheck($data)
    {
        if (!$data['id'] || !in_array($data['type'], $this->typesObjects)) return false;
 
        $this->ItemsToCheck[] = array ('id' => $data['id'], 'text' => (isset($data['text']) ? $this->codeText($data['text']) : ''), 'type' => $data['type'], 'name' => $this->codeText($data['name']), 'uservars' => isset($data['uservars']) ? $data['uservars'] : array());
        
        return true;
    }
 
    // функция кодирования текста
    private function codeText($text)
    {
        return base64_encode(@iconv('WINDOWS-1251', 'UTF-8//IGNORE', $text));
    }
    
    // функция выполнения запроса на проверку
    public function execRequest($create = 1)
    {
        // пытаемся создать xml файл с заданиями
        if ($create && !$this->createXml()) return false;
 
        // отправляем запрос на сервер антиплагиата
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->serverUrl[$this->serverType]);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, "xmlUrl=".$this->localServer.'antiplagiat/xml/'.basename($this->xmlPath)."&xmlAnswerUrl=".$this->localUrl.($this->sort ? '&sort='.$this->sort : ''));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        $json = curl_exec($ch);
        curl_close($ch);
 
        return str_replace('\,', ',', $json);
    }
    
    // функция построения xml файла заданий
    private function createXml()
    {
        $string = '<?xml version="1.0" encoding="UTF-8" ?'.'><root>';
 
        $string .= '<serverType>'.$this->serverType.'</serverType>';
 
        foreach ($this->ItemsToCheck as $item) {
            $string .= '
                <entry>
                    <id>'.$item['id'].'</id>
                    <type>'.$item['type'].'</type>';
 
            if (isset($item['uservars']) && $item['uservars'] && is_array($item['uservars'])) {
                $string .= '
                    <uservars>';
                foreach ($item['uservars'] as $key => $uservar)
                    $string .= '
                        <'.$key.'>'.$uservar.'</'.$key.'>';
 
                $string .= '
                    </uservars>';
            }
            $string .='
                    <name>'.$item['name'].'</name>'.
                    (isset($item['text']) && $item['text'] ? '<text>'.$item['text'].'</text>' : '').'
                </entry>';
        }
        
        $string .= '</root>';
 
        if (is_file($this->xmlPath)) unset($this->xmlPath);
 
        // шифруем данные
        if ($this->useCrypt) {
            $td = mcrypt_module_open (MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
            mcrypt_generic_init ($td, $this->useCrypt, $this->useCrypt);
            $string = mcrypt_generic ($td, $string);
            mcrypt_generic_deinit ($td);
            mcrypt_module_close ($td);
        }
        
        // сохраняем файл
        $f = @fopen($this->xmlPath, 'w') or die("Failed open file # ".$this->xmlPath." # on write");
        fwrite($f, $string, strlen($string));
        fclose($f);
 
        if (is_file($this->xmlPath)) return true;
        
        return false;
    }
}
 
?>
 
 
Постановка задания на проверку
 
 
// создаем объект для формирования запроса на проверку
$etxtPlagiat = new EtxtAntiPlagiat(md5(time()).'.xml', 1, 'server');
// доступность сервера
if (!$etxtPlagiat->isConnect || !($tmp = json_decode($etxtPlagiat->isConnect))) {
    logging('*** Ошибка соединения с сервером Антиплагиата');
    exit();
}
// выбираем объекты на проверку
$items = SELECT * FROM table
 
// добавляем все объекты на проверку
foreach ($items as $item) {
    // добавляем объект на проверку
    $etxtPlagiat->addItemToCheck(array('id' => $item['id'], 'text' => $item['text'], 'type' => $item['type'], 'name' => $item['title'], 'uservars' => $item['usersvars']));
}
 
// посылаем запрос серверу на проверку
if ($data = $etxtPlagiat->execRequest()) {
    if ($data = json_decode($data)) {
        logging(iconv('UTF-8', 'WINDOWS-1251//IGNORE', $data->Description));
        exit();
    }
}
    
 
Получение ответа от сервера
 
 
// проверка данных в ответе
if (!isset($_POST['Xml']) || !$_POST['Xml']) {
    logging('Данные в ответе сервера не найдены');
    exit();
}
 
$_POST['Xml'] = str_replace(' ', '+', $_POST['Xml']);
 
// расшифровываем данные
$td = mcrypt_module_open (MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
mcrypt_generic_init ($td, CHECK_KEY, CHECK_KEY);
$_POST['Xml'] = mdecrypt_generic ($td, base64_decode($_POST['Xml']));
 
// устанавливаем перехват ошибок
libxml_use_internal_errors(true);
 
// пытаемся преобразовать xml в объект
if ($xml = simplexml_load_string($_POST['Xml'])) {
    foreach ($xml->entry as $item) {
        ...
    }
}
 
AntiPlagiarism.NET -
Проверка текста на уникальность
Список преимуществ
  • Осуществляет пакетную проверку всех текстов из заданной директории
  • Аккуратно определяет уникальность текста
  • Находит и подсвечивает неуникальные фрагменты текста прямо на восстановленной копии веб-страницы
Бесплатная Демо-версия 1 день
Скачать
  • Определяет уникальность веб-страниц
  • Ищет совпадения по сохраненным копиям поисковиков
  • Работает со списком прокси и многое другое