GrabDuck: інтеграція з StackOverflow через StackExchange API

Вітаю читач,
сьогодні ми подивимося, як можна використовувати StackExchange API для того, щоб одержувати дані з сайтів цього сімейства, наприклад таких, як StackOverflow. Також, ми розглянемо, які можливості існують для просування додатків/сайтів, що використовують дане API на StackExchange і, насамкінець, покажемо як виглядає інтеграція з SO у нас на GrabDuck.



Зацікавило? Просимо під кат.



Вступ, або чому StackExchange

Для тих хто не знайомий з тим, що таке GrabDuck, проведемо короткий екскурс (більш докладно можна подивитися в попередній статті — GrabDuck: новий погляд на закладки).

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

Основна ідея сервісу — виступати таким собі центром, що збирає відкладене з різних джерел сторінки в одному місці та надавати універсальний механізм для пошуку.

Чому StackExchange? Аналізуючи статистику по збереженим документам, ми прийшли до висновку, що у нас дуже багато закладок з ІТ-орієнтованих сайтів, таких як Хабр або StackOverflow. Ці сайти дозволяють користувачам формувати своє вибране із статей або питань. «Ось», — подумали ми: «ще одне джерело, який наші користувачі зможуть налаштувати і отримувати періодичні оновлення своїх закладок з цих сервісів на GrabDuck». Почати вирішили з StackOverflow — це популярний ресурс не тільки у нас, але і за кордоном, у нього є зрозуміле і просте публічне API, а також велике ком'юніті.

Отже, наше завдання — зробити синхронізацію питань з вибраного StackOverflow. Назвімо більш близький нам сайт — StackOverflow російською.

StackExchange API

Як напевно всі знають, StackExchange це не один, а ціла група сайтів (або в термінології StackExchange — спільнот), об'єднаних однією ідеєю: запитання-відповіді. Найпопулярніші — так чи інакше пов'язані з ІТ-тематикою, це StackOverflow, російська версія StackOverflow, AskUbuntu, ThinkDifferent, SuperUser і багато інші.

Початкова точка для вивчення API — https://api.stackexchange.com/docs

Що зручно, не грає ролі з яким сайтом необхідно комунікувати — StackExchange надає єдиний API для всіх своїх сайтів. Тобто ми можемо один і той же запит для всіх сайтів генерувати і відправляти на api.stackexchange.com, а для того, щоб визначити який з сайтів должет його відпрацювати, нам необхідно задати спеціальний параметр (параметр site). В результаті можемо отримати різні відповіді від кожного сайту окремо.

Надсилати запити можна двома способами.
  1. Як зазвичай, посилаючи HTTP запити на api.stackexchange.com і отримуючи JSON відповідь або
  2. використовуючи спеціальну форму на самому stackexchange.com, яку можна використовувати для того, щоб попередньо переглянути, як працює та чи інша функціональність, або ж тут можна легко набити запит і потім просто перенести його в свій додаток.




API відкрите, що означає, що його можна використовувати без будь-якої попередньої реєстрації, правда при цьому кількість запитів обмежується 300 в день. Для того, щоб мати можливість відправляти більше запитів (до 10000 в день), краще все таки зареєструватися і отримати спеціальний ключ для свого додатка. У разі роботи з API через форму на сайті кількість викликів API також обмежено 10000 в день.

Але досить слів, перейдемо до справи. Ще раз нагадаю, що наше завдання — отримати список обраного, збережений користувачем на російською StackOverflow (він же HashCode.ru у недавньому минулому). Працювати будемо через форму на сайті.

Для початку нам необхідно зрозуміти, як визначити, що ми хочемо працювати саме з stackoverflow.ru або іншими словами, чому повинен дорівнювати параметр site у нашому запиті. Подивимося список всіх сайтів, що належать до StackExchange. Для цього йдемо в розділ документації Sites, запускаємо запит:

https://api.stackexchange.com/2.2/sites

і шукаємо в результатах необхідний нам StackOverflow російською

...,
{
"styling": {
"tag_background_color": "#FFF",
"tag_foreground_color": "#000",
"link_color": "#0077CC"
},
"related_sites": [
{
"relation": "meta",
"api_site_parameter": "meta.ru.stackoverflow",
"site_url": "http://meta.ru.stackoverflow.com",
"name": "Stack Overflow російською Meta"
},
{
"relation": "chat",
"site_url": "http://chat.stackexchange.com?tab=site&host=ru.stackoverflow.com",
"name": "Chat Stack Exchange"
}
],
"aliases": [
"http://hashcode.ua",
"http://stackoverflow.ua"
],
"markdown_extensions": [
"Prettify"
],
"open_beta_date": 1427414400,
"closed_beta_date": 1427414400,
"site_state": "open_beta",
"favicon_url": "http://cdn.sstatic.net/ua/img/favicon.ico",
"icon_url": "http://cdn.sstatic.net/ua/img/apple-touch-icon.png",
"audience": "програмістів",
"site_url": "http://ru.stackoverflow.com",
"api_site_parameter": "ru.stackoverflow",
"logo_url": "http://cdn.sstatic.net/ua/img/logo.png",
"name": "Stack Overflow російською",
"site_type": "main_site"
},...


Отриманий об'єкт містить всю необхідну інформацію про необхідному нам сайті. Наприклад, як позиціонують аудиторію творці (audience), Favicon і велике зображення для сайту (favicon_url та ison_url), колірну гаму, що може бути нам необхідна для будь-яких цілей (styling) і багато іншого. Крім того, бачимо необхідний параметр для виклику API (api_site_parameter), ru.stackoverflow.

Тепер у нас є всі дані, щоб сформувати запит на список обраного певного користувача. Для прикладу виберемо довільного користувача з id 16095 у якого є питання в обраному.

переходимо на сторінку Користувачі — Вибране (також доступна з розділу документації)

Коректуємо запит на потрібні нам параметри і запускаємо:

https://api.stackexchange.com/2.2/users/16095/favorites?order=desc&sort=activity&site=ru.stackoverflow

в результаті отримуємо те, що було нам потрібно — список «фаворитів» конкретного користувача:

{
"items": [
{
"tags": ["maven","java","idea","resources"],
"owner": {
"reputation": 11,
"user_id": 25194,
"user_type": "registered",
"profile_image": "https://www.gravatar.com/avatar/7b745015819bd1d9dbc17ac3f64a40f1?s=128&d=identicon&r=PG",
"display_name": "Slayfi",
"link": "http://ru.stackoverflow.com/users/25194/slayfi"
},
"is_answered":false,
"view_count": 162,
"answer_count": 0,
"score": 2,
"last_activity_date": 1433402068,
"creation_date": 1416248008,
"last_edit_date": 1433402068,
"question_id": 376200,
"link": "http://ru.stackoverflow.com/questions/376200/class-path-resourse-applicationcontext-xml-cannot-be-opened-because it-does-no",
"title": "Class path resourse [ApplicationContext.xml] cannot be opened because it does not exist"
},{
"tags": ["php","websocket"],
"owner": {
"reputation": 300,
"user_id": 19768,
"user_type": "registered",
"accept_rate": 93,
"profile_image": "https://www.gravatar.com/avatar/fa8fae6547dd2415a143680d337b1758?s=128&d=identicon&r=PG",
"display_name": "duhon",
"link": "http://ru.stackoverflow.com/users/19768/duhon"
},
"is_answered": false,
"view_count": 197,
"answer_count": 0,
"score": 4,
"last_activity_date": 1432902435,
"creation_date": 1414136622,
"last_edit_date": 1432902435,
"question_id": 370273,
"link": "http://ru.stackoverflow.com/questions/370273/%d0%9f%d1%80%d0%b0%d0%b2%d0%b8%d0%bb%d1%8c%d0%bd%d0%b0%d1%8f-%d0%b0%d1%80%d1%85%d0%b8%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b4%d0%bb%d1%8f-wamp-%d1%87%d0%b0%d1%82%d0%b0",
"title": "Правильна архітектура для wamp чату"
},...


Задача вирішена. Все просто, чи не правда?

Можливості по просуванню

Отже, наше додаток готове, що далі? Необхідно розповісти про нього людям. І тут StackExchange знову нам на допомогу.

Справа в тому, що існує офіційний спосіб дати опис на свою програму на самому SE. Докладний опис, як це зробити (правда тільки англійською) можна знайти на самому stackapps.com

Як приклад, як виглядає розміщене оголошення, наведемо опис GrabDuck на StackApps.com.

Сподіваюся наведена інформація буде корисна тим, у кого є ідеї, що можна зробити на основі сайтів StackExchange.

Як зробили синхронізацію з StackOverflow ми на GrabDuck

Подивимося тепер виглядає синхронізація у нас. Працювати будемо під тим же користувача з ID 16095

Отже після реєстрації, заходимо в особистий кабінет і вибираємо пункт «Синхронізація».
На даний момент користувачеві доступно 3 слота для синхронізації. Вибираємо необхідний нам сервіс (це StackOverflow російською) і натискаємо на кнопку «Додати новий сервіс».



Вводимо ID користувача. Натиснувши на кнопку «Перевірити», можна переконатися, що ID ввели правильно. Зберігаємо. Все, синхронізація налаштована.



Поточний статус синхронізації завжди можна подивитися в особистому кабінеті. А додаються на StackOverflow питання доступні разом з тегами для пошуку на GrabDuck.



Переваги такого підходу або навіщо синхронізувати вибране з SO на GD

Допитливий читач може запитати, а навіщо взагалі це потрібно? Я і так можу зайти на StackOverflow і знайти що мені потрібно там.

Так це правда, але що додатково пропонуємо ми на GD. Пошук відбувається не тільки за обраним з SO, але і по іншим закладок користувача, які теж можуть містити необхідну інформацію. Або користувач може налаштувати додаткові сервіси для синхронізації і шукати за документами з інших сайтів одночасно (а у нас в планах синхронізуватися з хабром, rss, delicious і багатьма іншими популярними сервісами). І все це, зауважте, без якоїсь активної участі користувача — все синхронізації одного разу налаштовані автоматично подгружают відстрочені матеріали на GD.

І на завершення статті, для тих, хто стежить за нами — невеликий огляд про те, що у нас нового з минулого разу

GrabDuck Update Log

З часу минулого статті пройшло трохи більше місяця. Що змінилося за цей час у нас.

Розширення для FireFox
У нас з'явилося розширення для «Лисиці». З особистих вражень — для хрому як-то все виглядає набагато простіше і логічніше. Спочатку, просто хотіли перенести код з Chrome без яких-небудь переробок на FF. Тому, коли робили розширення для Chrome, намагалися використовувати тільки HTML+CSS+JavaScript, щоб можна було в майбутньому перенести без яких-небудь доопрацювань на інші браузери. Не тут-то було. В FF, практично все, що можна зробити тільки з використанням свого специфічного API. Банальне, здавалося б приклад, відправити запит на сервер, тут просто не буде працювати, необхідно використовувати спеціальну функцію від FireFox Addon API. Тому довелося практично все переробляти заново. З підтвердженням розширень та ж пісня. Якщо для Хрому все пройшло відносно легко і гладко, то в FF обіцяють завершити процедуру схвалення за 3-5 днів, але на практиці поміщають в чергу, яка практично не рухається. Спочатку ми були там на 136 місці, за місяць з невеликим пересунулися на 106. Так що мабуть до зими наше розширення все таки буде розглянуто. Вообщем, як у них взагалі щось працює не зрозуміло, але зате стає ясно, чому Хром забирає у FF ринок (як би це не було сумно).

Теги при додаванні закладок
Стало можливо при додаванні закладок відразу ставити теги. Це доступно, як при додаванні через сайт, так і всіх розширень. Нам досі не подобатися цей спосіб, і ми віримо, що з часом зможемо запропонувати користувачам, щоб теги призначалися автоматично. Але після першої статті було багато прохань додати цю функціональність, тому поки вирішили піти назустріч і зробити.

Скріншоти сайтів
При парсингу сайтів ми намагаємося підібрати коротке зображення зі сторінки. Іноді це вдається, іноді зображення просто немає, а іноді з сайту можна зняти тільки маленькі зображення, які при розтягуванні виглядають аж не дуже красиво. Тому ми почали робити скріншоти сайтів. На жаль кількість закладок величезна і згенерувати за один підхід зображення для всього фізично не можливо. Тому поправили алгоритм парсинга і поки намагаємося знімати скріншоти тільки там, де це дійсно необхідно. Для цікавих — ми використовуємо Page2Images. На «спробувати», є безкоштовний акаунт з обмеженням у 100 url на добу і великим часом обробки кожного url. Якщо існують якісь кращі альтернативи, прошу залишати в коментарях.

Новий дизайн
Ні, ми не перемальовували на сайті кнопочки і не міняли кольори, але поступово прийшли до висновку, що незручно стрибати зі сторінки на сторінку між закладками, тегами і останніми документами і вирішили об'єднати все на одному екрані. Тепер користувач може відразу охопити поглядом все, що у нього є і вирішити, яким шляхом знайти, то що йому потрібно. «Редизайн» поки не завершений, ми хочемо переробити саму логіку доступу до документів, зробити її більш простою і зрозумілою. Але перший крок у цьому напрямку вже зроблено.

Синхронізація з StackExchange
Власне про це вся дана стаття. Крім самої синхронізації, GrabDuck також навчився правильно розставляти теги з усіх питань StackExchange спільнот, а також з усіх Хабра-сайтів. Будемо далі опрацьовувати цю ідею, і в майбутньому плануємо додавати синхронізації з іншими корисними сайтами і вчитися заповнювати за користувачів мета інформацію.

Історія переглядів
Реалізували історію просмоторов. Що це таке? Найпростіше пояснення — зроблено як на YouTube — коли є список «подивитися пізніше» / вибране і список усього переглянутого. Для нас, на практиці, це означає, що тепер є два списки — закладки користувача, відсортовані за датою додавання (так зване вибране) і історія переглядів, відсортована по даті прочитання, де знаходиться все що користувач використовував, включаючи документи з рекомендацій.

Дрібні доопрацювання і баги
Виправили безліч помилок і допрацювали механізм парсинга, розпізнавання сторінок і пошуку дублікатів. Чесно сказати, навіть не припускали, зі скількома порушеннями всього і вся можуть бути зроблені веб-сайти. Самий «страшний» приклад, який так і не придумали як обробляти — сторінка є і повертається з актуальних контентом, але з 500 (помилка на сервері) відповідь від сервера. Для браузера, це не грає ролі, він просто показує, що настав, а для нас це означає, що сторінка не валидна.

На цьому на сьогодні все. Запрошуємо всіх пробувати як працює нова функціональність і ділитися враженнями.
Підписуйтесь на наш твіттер, щоб бути в курсі всіх оновлень.
До зустрічі на GrabDuck!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.