API Медузы: пишем полнотекстовый RSS

от автора

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

Meduza.io — не исключение: текст приходит урезанный, приходится каждый раз переходить из ридера в браузер для прочтения одной новости. Особенно это выглядело ужасным, когда на Медузе не было нормальной мобильной версии, веб-версия на телефоне сильно тормозила.

Существуют различные сервисы для парсинга html в rss, но когда я наткнулся на консольный клиент для Медузы, у меня сразу же возник вопрос, а какое API там используется и можно ли его заюзать для написания своего приложения?

API

Далеко ходить не пришлось, код консольного приложения выложен на гитхабе и представляет собой js-ку, которая обращается к искомому API.

Получение списка новостей

https://meduza.io/api/v3/search?chrono=news&page=0&per_page=10&locale=ru
chrono — принимает значения news, cards, articles, shapito или polygon, в зависимости от рубрики, которую хотим получить;
page — номер страницы;
per_page — количество записей на странице;
locale — локаль ru или en;

Получение отдельной новости

https://meduza.io/api/v3/shapito/2015/06/02/vyshel-neofitsialnyy-terminalnyy-klient-meduzy
Тут просто подставляется url, полученный из прошлого пункта.

Идея

Взять исходный фид rss по адресу https://meduza.io/rss/all, но вместо урезанных новостей подставлять новость, полученную через API.

Пример реализации (прототип)

Я взял руби и написал немного кода для парсинга исходного rss фида:

Nokogiri::XML(open('https://meduza.io/rss/all'))

А также код, который парсит json отдельно взятой новости:

JSON::parse(open('https://meduza.io/api/v3/' + post_url).read)['root']['content']['body']

Подставляем одно в другое и получаем нечто следующее:

require 'open-uri' require 'json' require 'nokogiri'  $meduza = 'https://meduza.io' $meduza_rss = $meduza + '/rss/%s' $meduza_api = $meduza + '/api/v3/%s'  class Meduza   def Meduza.generate(feed = 'all')     doc = Nokogiri::XML(open($meduza_rss % feed))     doc.xpath('/rss/channel/item').each do |item|       post_id = item.xpath('link').inner_text.gsub(/^#{$meduza}\//, '')       json = JSON::parse(open($meduza_api % post_id).read)       item.search('description').each do |description|         description.content = json['root']['content']['body'].gsub('src="/image/', 'src="//meduza.io/image/')       end     end     doc.to_xml   end end  puts Meduza.generate

Попутно меняем относительные url картинок на абсолютные с помощью метода gsub.

Использование

Написано минималистичное приложение на sinatra, которое можно развернуть, например, на хостинге heroku и пользоваться на здоровье (и к тому же совершенно бесплатно). Избавиться от «засыпания» приложений на heroku поможет сервис вроде этого.

Исходный код приложения выложен на github, спасибо за внимание!

P. S. Ссылка на работающее приложение meduza.herokuapp.com/rss (до тех пор, пока бесплатный аккаунт heroku сможет выдержать нагрузку).

ссылка на оригинал статьи http://habrahabr.ru/post/259471/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *