Powershell скрипт: Чтение Вконтакте через RSS

Ранее оставлял ссылку на сайт который генерирует rss-ленту из страницы во Вконтакте: elims.org.ua/blog/kak-chitat-vkontakte-v-rss-lente. Но сайт стал настолько популярным, что для автора его содержание перестало быть выгодным. Теперь нет возможности с его помощью читать вконтакте через RSS. О чем мне и сказали в комментариях и попросили подсказать альтернативу.

  1. Написал скриптик на Powershell, который будет генерировать RSS-ленту из стены во Вконтакте
  2. Создал аналог умершего сервиса: https://elims.org.ua/vk-to-rss/

Пользуйтесь =)

Если хотите использовать вариант со скриптом, то вам понадобиться Powershell 3 или выше. Если Вы обновляете свой Windows, то Powershell нужной версии у Вас уже должен быть. Если же нет, то сначала понадобиться установить или убедиться что у Вас установлен Framework 4.5 и потом лишь установить Powershell 4:

  • Framework 4.5: microsoft.com/ru-ru/download/details.aspx?id=30653
  • Powershell 4: social.technet.microsoft.com/wiki/contents/articles/21016.how-to-install-windows-powershell-4-0.aspx

Версию своего Powershell можно увидеть в столбце "Major" через команду:

powershell $host.version

Сначала публикую код скрипта, а ниже пояснения что с этим делать.

Powershell-скрипт для чтения Вконтакте через RSS

Код:

#перечисляем через запятую id людей или пабликов, id пабликов должны начинаться со знака "-":
$page_ids = 5358898,-5994278,-31976785,-29358490,-62043361,-33393308,-24565142 
$rss_path = "C:\Dropbox\Temp\" #папка в которой будут храниться RSS-ленты
$antispam = "kitai2.ivanchursin.ru","Как зарабатывать на Китае с нуля","Водоотталкивающая одежда","Александр Мартынов" #антиспам
$date = Get-Date -format yyyy-MM-dd
$file_log = "C:\Temp\vk-to-rss_log-" + $date + ".txt" #файл лога
foreach ($page_id in $page_ids) { #для каждого id
 Start-Sleep -s 1 #задержка в 1 секунду, чтобы не превысить лимит обращений к api
 $url = "http://api.vk.com/method/wall.get?owner_id="+$page_id+"&count=100" #ссылка для получения 100 последних записей со стены
 $request = Invoke-WebRequest -Uri $url #запрашиваем ссылку
 $wall_array = $request.content | ConvertFrom-Json #Конвертируем полученные данные из формата JSON в массив 
 $UnixTimeStart = New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0 #указываем дату, с которой стартовал отсчет unix-времени
 $HumanDateTime = $UnixTimeStart.AddSeconds($wall_array.Response[1].date) #добавляем к дате количество секунд unix-времени
 $RFC_DateTime = $HumanDateTime.ToString("r") #переводим формат даты в r-формат - дата по стандарту RFC1123  
 Start-Sleep -s 1
 if ($page_id -lt 0) { #если id страницы меньше 0, то есть со знаком "-" впереди
  $group_id = $page_id*-1 #то умножаем id на -1 и получаем его без знака "-"
  $url = "http://api.vk.com/method/groups.getById?gid="+$group_id #получаем информацию о группе
  $request = Invoke-WebRequest -Uri $url
  $response_array = $request.content | ConvertFrom-Json #Конвертируем полученные данные из формата JSON в массив 
  $page_name = $response_array.response.name #имя сообщества
 }
 else {
  $url = "http://api.vk.com/method/users.get?uids="+$page_id #получаем информацию о странице
  $request = Invoke-WebRequest -Uri $url
  $response_array = $request.content | ConvertFrom-Json #Конвертируем полученные данные из формата JSON в массив 
  $page_name = $response_array.response.first_name + " " + $response_array.response.last_name #имя страницы
 }
 "Обрабатывается подписка:" + $page_name
 if ($page_name.length -lt 1) { 
  $time = "{0:yyyy-MM-dd HH:mm:ss}" -f (get-date)
  $string = $time + " ОШИБКА! ПУСТОЕ ИМЯ СТРАНИЦЫ! ПРЕРЫВАЕМ РАБОТУ СКРИПТА!"
  $string | Out-File -Append $file_log -Encoding UTF8 
  Break
 }
 $feed = "<?xml version=""1.0"" encoding=""UTF-8""?> 
<rss version=""2.0"" xmlns:content=""http://purl.org/rss/1.0/modules/content/""> 
 <channel> 
 <title>$page_name</title> 
 <link>http://vk.com/id$page_id</link> 
 <description>Страница: http://vk.com/id$page_id</description> 
 <lastBuildDate>$RFC_DateTime</lastBuildDate>"
 $i=1
 Do {
  $text = "<![CDATA[" + $wall_array.Response[$i].text #текст записи
  $wall_id = $wall_array.Response[$i].id #id записи
  $spam_boolean = 0
  foreach ($spam in $antispam) {
   if ($text.Contains($spam)) { 
    "Обнаружен спам! Запись не будет включена в ленту: " + $spam + " in vk.com/wall" + $page_id + "_" + $wall_id 
    $spam_boolean = 1
   }
  } 
  if ($spam_boolean -eq 0) { 
   $HumanDateTime = $UnixTimeStart.AddSeconds($wall_array.Response[$i].date) #добавляем к дате количество секунд unix-времени
   $RFC_DateTime = $HumanDateTime.ToString("r") #переводим формат даты в r-формат - дата по стандарту RFC1123
   if ($wall_array.Response[$i].attachments.count -gt 0) { #если есть какие-либо вложения 
    foreach ($attachment in $wall_array.Response[$i].attachments) { #то для каждого вложения 
     if ($attachment.type -eq "photo") {$text = $text + "<br><img src='"+$attachment.photo.src_big+"'/>"} #если вложение - фотография
     if ($attachment.type -eq "link") {$text = $text + "<br><a href='"+$attachment.link.url+"'>"+$attachment.link.title+"</a>"} #если вложение - ссылка
     if ($attachment.type -eq "doc") {$text = $text + "<br><a href='"+$attachment.doc.url+"'>"+$attachment.doc.title+"</a>"} #если вложение - документ
     if ($attachment.type -eq "video") {$text = $text + "<br>Видео:<br><a href='http://vk.com/video"+$attachment.video.owner_id+"_"+$attachment.video.vid+"'><img src='"+$attachment.video.image_big+"'/></a>"} #если вложение - видео 
    }
   }
   $text = $text + "]]>"
   $feed = $feed + "
<item>
 <title>Запись за: $HumanDateTime</title>
 <link>http://vk.com/wall"+$page_id+"_$wall_id</link>
 <pubDate>$RFC_DateTime</pubDate>
 <description>$text</description>
</item>"
  } 
  $i++
 } While ($i -lt $wall_array.Response.length) #пока не обойдем все полученные записи
 $feed = $feed + "</channel></rss>" 
 $rss_file = $rss_path + "RSS_" + $page_id + ".xml"
 $feed | Out-File -FilePath $rss_file -Encoding UTF8 #сохраняем сгенерированный xml-файл 
 $time = "{0:yyyy-MM-dd HH:mm:ss}" -f (get-date)
 $string = $time + " Сгенерирован RSS Поток для " + $page_name
 $string | Out-File -Append $file_log -Encoding UTF8 #запись в лог файл
}

Указываем страницы на которые хотим подписаться

Обратите внимание на самую первую строку скрипта:

$page_ids = 5358898,-5994278,-31976785

В этой строке через запятую указываем id страничек, на которые хотим подписаться. Id групп и пабликов всегда начинаются со знака "-". В моем примере я подписался на страницу своего профиля во Вконтакте  - vk.com/id5358898 (она же - vk.com/demyanovich) и на два сообщества: vk.com/club5994278 (оно же vk.com/picblog) и vk.com/public31976785 (оно же vk.com/club31976785 или vk.com/science_technology)

Возникает вопрос: "как узнать id страницы профиля, группы или паблика, если они используют такие имена как vk.com/demyanovich или vk.com/science_technology?"

Узнать можно большим количеством способов, пример моего способа:

  • Ссылка api.vk.com/method/users.get?uids=demyanovich покажет Id страницы профиля vk.com/demyanovich: "uid":5358898
  • Ссылка api.vk.com/method/groups.getById?gid=science_technology покажет Id группы или паблика vk.com/science_technology: "gid":31976785. Помните что к id групп и пабликов нужно спереди добавлять знак "-"

Для каждого id будет сгенерирован отдельный rss-файл, на который нужно будет подписаться.

Указываем где хранить RSS-файлы

Теперь обратите внимание на вторую строку скрипта:

$rss_path = "C:\Dropbox\Temp\" #папка в которой будут храниться RSS-ленты

Указываем папку где у Вас будут храниться файлы сгенерированных rss-лент (адрес папки обязательно должен заканчиваться на "\"). Именно на эти ленты Вы и будете подписываться.

Если вы читаете ленты с локального компьютера в локальном RSS ридере - то в настройках RSS-ридера указываете локальный адрес к rss-файлу, например: "C:\Dropbox\Temp\RSS_5358898.xml". Если же вы читаете RSS через онлайн RSS-агрегаторы, такие как Google Reader, InoReader, Feedly, то нам понадобиться чтобы эти rss-файлы были доступны из интернета. Именно потому я складываю их в папку Dropbox, благодаря Dropbox файл "C:\Dropbox\Temp\RSS_5358898.xml" можно сделать доступным по ссылке dropbox.com/s/lwd46yf1xqhl9et/RSS_5358898.xml, именно на эту ссылку я и подписываюсь. Вы можете сделать у себя тоже самое через один из множества сервисов синхронизации файлов.

Как запускать скрипт

Осталось заставить работать этот скрипт, то есть сделать чтобы он регулярно генерировал rss-файлы для Ваших подписок. Для этого нам понадобится стандартный планировщик заданий в  Windows: запускаем "Панель управления - Администрирование - Планировщик заданий" и создаем задачу.

Можно задачу создать при помощи команды: запускаем консоль от имени администратора и пишем исходя из моего примера:

Schtasks.exe /create /tn "vk-to-rss" /sc minute /mo 15 /tr "Powershell -File C:\Dropbox\Programming\PowerShell\vk-to-rss.ps1" /s "elims-pc" /ru "SYSTEM"

Где:

  • vk-to-rss - имя задачи
  • /sc minute /mo 15 - запускать раз в 15 минут
  • C:\Dropbox\Programming\PowerShell\vk-to-rss.ps1 - адрес где находится мой powershell  скрипт
  • elims-pc - имя моего компьютера
  • SYSTEM - задача запускается из под системной учетной записи (для того чтобы не надоедали всплывающие окна во время работы скрипта

Пытался писать кратко, потому если что-либо не понятно - спрашивайте в комментариях.

Если есть предложения по совершенствованию скрипта, тоже пишите в комментариях.

Могу переписать скрипт на php и развернуть свой онлайн сервис для генерации лент из вконтакте, сделать аналог vkontakte-feed.appspot.com, но тогда придется например в каждой десятой rss-записи показывать рекламу, чтобы сервис сам себя окупал. Пока откладываю идею в ящик, но если вдруг в комментариях появиться множество желающих - это может мотивировать таки сделать такой сервис =)

Понравилось? =) Поделись с друзьями:

Обсуждение записи “Powershell скрипт: Чтение Вконтакте через RSS”

  1. alexbess says:

    >Если же вы читаете RSS через онлайн RSS-агрегаторы, такие как Google Reader

    А тут можно поподробнее? Гуглоридер же вроде как всё…

  2. Владимир Демянович (elims.org.ua) says:

    alexbess, он упомянут для тех, кто раньше пользовался Google Reader, но позже так и не нашел альтернативу. А значит не знаком с современными аналогами)

  3. alexbess says:

    Владимир Демянович, понял:) За скрипт спасибо, попытаюсь расковырять:) Вконтактные новости всё-таки удобнее в рсс читать:)

  4. Владимир Демянович (elims.org.ua) says:

    alexbess, на здоровье)

  5. Владимир Демянович (elims.org.ua) says:

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

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

  6. alexbess says:

    Владимир Демянович, да, рекламные посты одолевают..

  7. еее says:

    Владимир, спасибо за пост ! Но, если есть возможность — сделайте все-таки аналог мегапопулярного vkontakte-feed.appspot.com — общественность только низко поклонится.. Уж на крайняк с рекламой (если уж альтруизма мао =)
    Спасибо!

  8. Владимир Демянович (elims.org.ua) says:

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

    После чего буду следить за нагрузкой сервера. Если вдруг она значительно возрастет — то придется отключать или придумывать что-то =) А так по началу , пока мало подписок можно будет экспериментировать =)

  9. Владимир Демянович (elims.org.ua) says:

    Существенно доработан скрипт. Имена подписок теперь будут отображаться в RSS агрегаторе, введена задержка запросов к API чтобы не превысить лимиты, введен антиспам и пр.

  10. ot says:

    подписываюсь под просьбой сделать аналог vkontakte-feed.appspot.com , пусть даже и с рекламой. спасибо вам! буду следить за новостями

  11. Владимир Демянович (elims.org.ua) says:

    Спешу обрадовать =) Аналог почти готов, уже с его помощью читаю один из пабликов вконтакте. Потестю пару деньков, продумаю некоторые нюансы и опубликую на блоге.

  12. alexbess says:

    При подписке ругается: Sorry. Something went wrong:400 — { «errorCode»:400, «errorId»:»ap5-sv2.2014081700.123240″, «errorMessage»:»invalid stream id: undefined» }

  13. alexbess says:

    Ругается в feedly……. В Inoreader’е подписался…

  14. Владимир Демянович (elims.org.ua) says:

    alexbess: elims.org.ua/vk-to-rss/ =)

    а ругается на что? На подписку сгенерированную через Powershell-скрипт?

  15. js says:

    Можно как-то доделать скрипт так, чтобы он заголовки новостей показывал, вместо «Запись за число:месяц:год время»?

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

  16. js says:

    Забыл дописать, спасибо за скрипт.

  17. zeal0t says:

    А для закрытых групп есть решение на ps?

  18. Владимир Демянович (elims.org.ua) says:

    js: заголовки новостей во вконтакте? =) Их там вроде не существует. На php он переписан, правда не в паблике, он работает в виде сервиса вот тут: https://elims.org.ua/vk-to-rss/

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

  19. js says:

    >заголовки новостей во вконтакте? =)
    Ну как-то обрезать первые строчки\у страницы (до одного предложения или кол-ва символов, как в твиттере (140), делают же как-то другие ридеры эти заголовки.

    >в виде сервиса вот тут
    А можно не в виде сервиса, а в виде скрипта? Себе поставить на сервер и не зависеть от внешних сервисов?

  20. Светлана says:

    https://elims.org.ua/vk-to-rss/ почему то с 23 декабря перестал работать. Было очень удобно. Подобного не могу найти нигде

  21. Владимир Демянович (elims.org.ua) says:

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

    Сегодня был в супермаркете но забыл купить =) В следующий раз может быть не забуду)

Обсудить