Додавання пропозицій до пошукового плагіна

Влад Мержевич

Пошуковик Google був одним з перших, хто додав до свого пошуку пропозицію популярних запитів - ви набираєте текст і одразу отримуєте список слів, що починаються з введених символів. В майбутньому ця технологія стала настільки популярною, що тепер її можна зустріти всюди. Також вона включена в специфікацію OpenSearch, на основі якої працює пошуковий плагін для браузера.

Підключити можливість показувати пропозиції в пошуку браузера досить просто, для цього слід у файл search.xml додати наступний рядок.

<Url type="application/x-suggestions+json" template="http://mysite.ru/suggestion.php?q={searchTerms}"/>

Тут файл suggestion.php відповідає за отримання запиту за методом GET і віддачу результатів. Сам запит вставляється замість ключового слова {searchTerms}, воно стандартно і незмінно, а змінна q довільна. Шлях до файлу suggestion.php, а також його ім'я також залежать від вподобань розробника і можуть легко бути замінені на інше.

Сам файл search.xml, наприклад, для сайту html.in.ua з урахуванням вищевикладеного виглядає наступним чином.

Приклад 1

<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
  <ShortName>html.in.ua</ShortName>
  <Description>Пошук по html.in.ua</Description>
  <Image height="16" width="16" type="image/x-icon">http://html.in.ua/favicon.ico</Image>
  <Url type="text/html" method="GET" xmlns:referrer="http://a9.com/-/opensearch/extensions/referrer/" 
       template="http://html.in.ua/sites/search/?q={searchTerms}"/>
  <Url type="application/x-suggestions+json" 
       template="http://html.in.ua/sites/search/suggestion.php?q={searchTerms}"/>
  <InputEncoding>UTF-8</InputEncoding>
  <AdultContent>false</AdultContent>
</OpenSearchDescription>

Формат даних

Файл suggestion.php при запиті повертає наступні дані у форматі JSON (JavaScript Object Notation, представлення об'єктів JavaScript).

  • Рядок запиту
  • Результати пошуку
  • Примітки
  • Адреса сторінки

Загальна кількість результатів не повинна перевищувати десять. Обов'язково повинні повертатися рядок запиту і результати пошуку, примітки і адреси за бажанням можна опустити.

Як приклад візьмемо кольори. Користувач вводить символи "ма", на які починаються кольори з нашого списку: магнолія (f8f4ff), малиновий (dc143c), мандариновий (f28500), маренго (4c5866). У дужках вказано значення кольору у шістнадцятковій системі, воно ж буде і адресою сторінки. У підсумку результат буде таким.

Приклад 2

["ма",
 ["магнолія",
  "малиновий",
  "мандариновий",
  "маренго"],
 ["http://mysite.ru/f8f4ff",
  "http://mysite.ru/dc143c",
  "http://mysite.ru/f28500",
  "http://mysite.ru/4c5866"]]

Кожний блок відправлених даних береться в квадратні дужки, а сам результат цілком також, блоки розділяються між собою комами. Спершу пишеться введене користувачем слово, потім в квадратних дужках результат пошуку, останніми йдуть адреси. У цьому прикладі примітки опущено з непотрібності.

У загальному випадку повертані дані мають наступний формат.

["рядок запиту",
 ["результат пошуку 1", " результат пошуку 2", ...],
 ["примітка 1", "примітка 2", ...],
 ["адреса  1", "адреса 2", ...]
]

Браузер Firefox не відображає примітки, незважаючи на їх наявність, а Internet Explorer виводить примітки нижче результатів пошуку.

На цьому прості речі закінчуються, і починається багато, багато програмування. У якості основи я обрав PHP за його популярність і певну простоту.

Програмуємо файл suggestion.php

Відправка даних браузеру розбивається на три завдання:

  1. отримання введеного користувачем тексту;
  2. вибір даних, що починаються з вказаних символів;
  3. відправка отриманих даних у форматі JSON.

Отримання даних через метод GET виконується за допомогою масиву $_GET['q'], де q це змінна, задана в файлі search.xml (приклад 1). Таким чином, отримання даних скорочується до наступного рядка.

$query = $_GET['q'];

Вибір потрібних даних залежить від способу їх зберігання, це може бути база даних, текстовий файл або масив. У якості прикладу візьмемо варіант з масивом.

Приклад 3

<?php
$url = 'http://mysite.ru/'; // Адреса сайту
$data = array ( // Масив з даними
  'color' => array ('білий', 'жовтий', 'магнолія', 'малиновий', 'мандариновий', 'маренго', 'чорний'),
  'url' => array ('ffffff', 'ffff00', 'f8f4ff', 'dc143c', 'f28500', '4c5866', '000000')
);

// 1. Отримуємо запит
// --------------------------------------
$query = mb_strtolower($_GET['q']);
$query = mb_convert_encoding($query, 'UTF-8', 'windows-1251');
$len = strlen($query); // Довжина рядка 

// 2. Шукаємо співпадіння
// --------------------------------------
// Введено не менше двох символів 
if (isset($query) && $len >= 2) {
  $i = 0; // Обнуляємо лічильник
  $res = array(); // Масив з результатами
  // Проходимося по всьому масиву
  foreach ($data['color'] as $item) {
    // Обмежуємо вивід 10 результатами
    if ($i >= 9) break;
    if ($query == substr($item, 0, $len)) {
    // Є співпадіння
    $res[] = $i;
  }
  $i++;
  }

// 3. Обробляємо і виводимо результати
// --------------------------------------
  if (isset($res[0])) {
    $output = '["'. $query . '",' . "\n";
    $output .= '[';
    $n = count($res); // Кількість результатів
    // Результати пошуку
    for ($i=0; $i<$n; $i++) {
      if ($i == $n-1) $semi = '"'; // в кінці видаляємо кому
      else $semi = '",';
      $output .= '"' . $data['color'][$res[$i]] . $semi . "\n";
    }
    $output .= "],\n";
    $output .= '[';
    // Адреси
    for ($i=0; $i<$n; $i++) {
      if ($i == $n-1) $semi = '"'; // в кінці видаляємо кому
      else $semi = '",';
      $output .= '"' . $url . $data['url'][$res[$i]] . $semi . "\n";
    }
    $output .= "]]";
    echo $output;
  }
} 
?>

Результат роботи програми можна перевірити, звернувшись до файлу за адресою suggestion.php?q=ма. При правильній роботі буде виведений текст, як у прикладі 2.

Internet Explorer

Браузер IE, починаючи з версії 8.0, не тільки підтримує специфікацію OpenSearch, але і розширює її за рахунок використання XML. Крім формату JSON дані можна повертати також у форматі XML (eXtensible Markup Language, розширювана мова розмітки), причому не тільки текст, але і зображення. Так, приклад 2 для цього формату змінить свій вигляд і матиме наступну структуру.

<?xml version="1.0"?>
<SearchSuggestion xmlns="http://schemas.microsoft.com/Search/2008/suggestions">
<Query>ма</Query>
 <Section>
  <Item>
   <Text>магнолія</Text>
   <Image source="http://mysite.ru/f8f4ff.png" alt="Магнолія" width="75" height="75"/>
   <Url>http://mysite.ru/f8f4ff</Url>
  </Item>
  <Item>
   <Text>малиновий</Text>
   <Image source="http://mysite.ru/ dc143c.png" alt="Малиновий" width="75" height="75"/>
   <Url>http://mysite.ru/dc143c</Url>
  </Item>
  <Item>
   <Text>мандариновий</Text>
   <Image source="http://mysite.ru/ f28500.png" alt="Мандариновий" width="75" height="75"/>
   <Url>http://mysite.ru/f28500</Url>
  </Item>
  <Item>
   <Text>маренго</Text>
   <Image source="http://mysite.ru/4c5866.png" alt="Маренго" width="75" height="75"/>
   <Url>http://mysite.ru/4c5866</Url>
  </Item>
 </Section>
</SearchSuggestion>

Незважаючи на деякі переваги, формат XML для пошуку не є універсальним і працює лише для браузера IE. Тому деталей дотикатися не буду, зацікавленим рекомендую російськомовну статтю на сайті Microsoft, присвячену створенню пошукового плагіна під Internet Explorer.

Сайти на тему

Часті запитання