«Терпение и труд — всё перетрут»

Введение


"Шок! Он умер" — отправка SMS с таким содержанием — пройденный этап в формировании православного сообщества в нашем городе. Во время отпуска на основной работе решил свою группу Миасс Православный во ВКонтакте вывести из летаргического сна на новый уровень. Сделать её интересной, массовой и самоуправляемой.
Потратил на это 0 руб. 0 коп и много свободного времени. Кое-что получилось.



Делюсь идеями, формулировками, python-кодом и другими плюшками. Хочу обратной связи.

Правда заключается в том, что хоть я и технарь по образованию, а вот программировать красиво не умею.
Но когда хочется сделать полезное для общества — почему бы не попробовать взять быка за рога?
Быком оказался — Python 2.7, правда была ещё корова — PyQt и маленький бычок: VK API — только об этом далее, а сначала нужно было поставить цель.

Цель поставлена


  • Увеличить число участников в 2 раза (начиная с ~4000 чел.)
  • Увеличить среднесуточное посещение до 100 человек в день (среднесуточное посещение до начала эксперимента: ~40 чел.)
  • Повысить качество записей на стене группы (контролируемый параметр: количество лайков и репостов)
  • Минимизировать свои трудозатраты (время пребывания онлайн довести до 2 часов в день)

Ну что? Поехали.

Стратегия, идеи, формулировки


Принцип моих телодвижений — простой. Ищу людей ВКонтакте, мировоззрение которых указано как «православие». Предлагаю дружить. Предлагаю вступить в группу своим православным друзьям. Группа растет. Каждому участнику группы предлагаю стать редактором (с возможностью постить записи на стене от имени группы) и модерировать сообщество. Самостоятельно добавляют топовые новости на стену, стараюсь комментировать существующие записи и обязательно перепост в другие мои группы и друзьям.

Вроде бы всё просто. Но есть несколько сложностей:
  1. Поиск по пользователям не дает возможность фильтровать людей по религиозным взглядам
  2. Ограничения в Vkontakte (на приглашения в группу — 40 человек день, на добавления в друзья — 50 человек, на отправку личных сообщение и прочее)
  3. Он/она, ты/Вы и другие формулировки сообщений. Когда автоматизируешь действия очень сложно угодить каждому, поэтому приходится выворачиваться и с одной стороны никого не обидеть и не напрячь, а с другой — достичь цели
  4. Поиск по новостям не сразу дает нужные результаты
  5. Трудоемко делать перепосты в ручную

Исходя из этого было принято решение автоматизировать действия, сформулировать адекватные тексты для сообщений, создать скрипты для фильтрации топовых новостей из ленты.

Например, личное сообщение участникам группы звучит так: «Сделаю редактором сообщества „Миасс Православный“ — это дает возможность писать от имени группы. \nПрошу пригласить в группу своих друзей =здесь URL= \nСпасибо!»
Заметьте, это сообщение легко читается взрослому и молодому, парню и девушке, другу (с которым на ты) и знакомому. На мой взгляд достаточно мягкая формулировка, не напряжная, приходит один раз (контроль повторов встроены в скриптах). А главное достигает цели, но об этом чуть позже — сейчас я расскажу про…

Инструменты и код


VkBot

Не помню когда я познакомился с этой маленькой программкой, но её бесплатная версия помогла автоматизировать то, что я делал:
  • приглашение в друзья своих товарищей — тех, кто является православным христианином (как их найти ВКонтакте — ниже) в моем городе.
  • Приглашение друзей в свою группу
  • Помощь в рассылке сообщение друзьям

В общем-то, это был толчок к написанию своих скриптов, так как не всё вкбот умеет… поэтому я посмотрел в сторону…

Python

Язык очаровал меня сразу… (Наверно нечто подобное было в раю — эта всем известная история про яблоко плод и питона змея...). Многое в его освоении почерпнул из хабра, но главное это то, что легко нашлись модули для работы с движком ВКонтакте, создания графического интерфейса (сначала осваивал tkinter, но потом познал прелести PyQt — во многом благодаря MonkeyStudio), графиков и много чего ещё.
Например, для комфортной работы с API ВКонтакте установка модуля VkApi делается в два действия:
sudo easy_install vk_api
sudo easy_install requests

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

IEP

Выглядит он так:

А нравится мне тем, что может
  • Отображать файловую структуру и структуру кода (можно делать закладки и скрывать/разворачивать вид)
  • Много вкладок, возможность работать с main проектами (удобно для PyQt), консоль и log — и все это можно отключить/включить внутри окна
  • Настройка горячих клавиш (причем по две комбинации на действие) — позволит легко перейти с любого другого редактора
  • Возможность запускать кусочки года, отдельные файлы или скрипты, или main проекты
  • Легкий и быстрый и удобно использовать в связке с облачными сервисами (я файлы в dropboxe/Яндекс.Диск храню — удобно для действий на работе или дома
  • Ну и для любителей opensource — редактор с BSD лицензией запуститься и на linuxe и в винде



Инструменты есть, как заставить себя работать? Для этого я сделал…
Закладки и напоминания

У меня есть вот такая закладка в планинге:


А в моем Androide через Google.Календарь приходит такое вот оповещение (VKBOT — значит надо запустить скрипт):


Это меня очень выручает. В планах посмотреть в сторону autoit или server+python+cron и автоматизировать эти повторяющиеся рутинные действия, когда приходится в ручную запускать скрипты и другие инструменты.

Итак. Вот мой рабочий стол — моя кухня.


Что дальше?
Кусочки кода

ID православных пользователей ВКонтакте
# -*- coding: utf-8 -*-
import vk_api
import time
import re


def vko():
    login = 111#Логин от ВК
    password = 222#Пароль от ВК
    try:
        vk = vk_api.VkApi(login, password)  # Авторизируемся
    except vk_api.authorization_error as error_msg:
        print(error_msg)  # В случае ошибки выведем сообщение
        return  # и выйдем
    
    relig='Православие' #кстати можно вводить, например, "Христианство", "Протестантизм" и др.
    goroda=(7159, 81) # через запятую можно перечислить все города и поселки по соседству 
    for gorod in goroda:
        values1 = {'city': gorod,'religion':relig} #Получение списка участников группы
        response1 = vk.method('users.search', values1)
        kolvo=response1['count']
        print('количество православных жителей в городе:№'+str(gorod)+' равно='+str(kolvo)+' чел')
        if kolvo<1:
            print('этот город пропустим')
        elif kolvo<1000:
            telsea=0
            indx=0
            file = open(str(gorod)+relig+'.txt', 'w')
            time.sleep(5)        
            values = {'fields': 'contacts','city': gorod,'religion':relig,'count':1000,'sort': 1}
            response = vk.method('users.search', values) #инфа об участниках. Разом
            print('_'*10+relig+'_'*10+'чел:'+str(kolvo)+'_'*10+'Город:'+str(gorod)+'_'*10)
            gran=response['count']
            if gran>1000:
                gran=1000
            for usdx in range(0,gran):
                indx=indx+1
                try:
                    mobile_phone = response['items'][usdx]['mobile_phone']
                    match1 = re.search("[\.\?\*]", mobile_phone) #Если эти символы есть
                    match2 = re.search("[0-9]", mobile_phone) #Если цифр нет
                    if (mobile_phone=='')or match1 or not(match2):
                        continue
                except:
                    mobile_phone = u'не указан'
                    continue
                try:
                    first_name = response['items'][usdx]['first_name']
                except:
                    first_name = u'имя нет'
                try:
                    last_name = response['items'][usdx]['last_name']
                except:
                    last_name = u'ФАМИЛИИ нет'
                vivod ='http://vk.com/id'+str(response['items'][usdx]['id'])+'\t'+str(gorod)+u'\t'+last_name+'\t'+first_name+u'\t'+mobile_phone+u'\t'+'\n'
                try:
                    vivod = vivod.encode("KOI8-R")	
                except:
                    vivod = 'Ошибка пользователя id='+str(response['items'][usdx]['id'])
                percent = (100.0/kolvo)*indx
                print('Выполнено:'+str(percent)+'%\t')#+vivod
                file.write(vivod)
                telsea=telsea+1		
            file.close
            print('_'*35+relig+'_'*3+'найдено:'+str(telsea)+' это в процентах:'+str(100.0/kolvo*telsea)+'_'*35)
        
        elif kolvo<9000:
            telsea=0
            indx=0
            file = open(str(gorod)+relig+'.txt', 'w')
            for birth_month in range(1,13):
                time.sleep(5)        
                values = {'fields': 'contacts','birth_month':birth_month,'city': gorod,'religion':relig,'count':1000,'sort': 1}
                response = vk.method('users.search', values) #инфа об участниках. Разом
                print('_'*10+relig+'_'*10+'чел:'+str(kolvo)+'_'*10+'Месяц:'+str(birth_month)+'_'*10+str(gorod)+'_'*10)
                gran=response['count']
                if gran>1000:
                    gran=1000
                for usdx in range(0,gran):
                    indx=indx+1
                    try:
                        mobile_phone = response['items'][usdx]['mobile_phone']
                        match1 = re.search("[\.\?\*]", mobile_phone) #Если эти символы есть
                        match2 = re.search("[0-9]", mobile_phone) #Если цифр нет
                        if (mobile_phone=='')or match1 or not(match2):
                            continue
                    except:
                        mobile_phone = u'не указан'
                        continue
                    try:
                        first_name = response['items'][usdx]['first_name']
                    except:
                        first_name = u'имя нет'
                    try:
                        last_name = response['items'][usdx]['last_name']
                    except:
                        last_name = u'ФАМИЛИИ нет'
                    vivod ='http://vk.com/id'+str(response['items'][usdx]['id'])+'\t'+str(gorod)+u'\t'+last_name+'\t'+first_name+u'\t'+mobile_phone+u'\t'+'\n'
                    try:
                        vivod = vivod.encode("KOI8-R")	
                    except:
                        vivod = 'Ошибка пользователя id='+str(response['items'][usdx]['id'])
                    percent = (100.0/kolvo)*indx
                    print('Выполнено:'+str(percent)+'%\t')#+vivod
                    file.write(vivod)
                    telsea=telsea+1		
                file.close
                print('_'*35+relig+'_'*3+'найдено:'+str(telsea)+' это в процентах:'+str(100.0/kolvo*telsea)+'_'*35)
        else:
            telsea=0
            indx=0
            file = open(str(gorod)+relig+'.txt', 'w')
            values1 = {'city': gorod,'religion':relig} #Получение списка участников группы
            response1 = vk.method('users.search', values1)
            kolvo=response1['count']
            for birth_month in range(1,13):
                for birth_day in range(1,32):
                    time.sleep(15)        
                    values = {'fields': 'contacts','birth_day':birth_day,'birth_month':birth_month,'city': gorod,'religion':relig,'count':1000,'sort': 1}
                    response = vk.method('users.search', values) #инфа об участниках. Разом
                    print('_'*10+relig+'_'*10+'чел:'+str(kolvo)+'_'*10+'Месяц:'+str(birth_month)+'    День:'+str(birth_day)+'_'*10+str(gorod)+'_'*10)
                    gran=response['count']
                    if gran>1000:
                        gran=1000
                    for usdx in range(0,gran):
                        indx=indx+1
                        try:
                            mobile_phone = response['items'][usdx]['mobile_phone']
                            match1 = re.search("[\.\?\*]", mobile_phone) #Если эти символы есть
                            match2 = re.search("[0-9]", mobile_phone) #Если цифр нет
                            if (mobile_phone=='')or match1 or not(match2):
                                continue
                        except:
                            mobile_phone = u'не указан'
                            continue
                        try:
                            first_name = response['items'][usdx]['first_name']
                        except:
                            first_name = u'имя нет'
                        try:
                            last_name = response['items'][usdx]['last_name']
                        except:
                            last_name = u'ФАМИЛИИ нет'
                        birthday=str(birth_day)+'.'+str(birth_month)
                        vivod ='http://vk.com/id'+str(response['items'][usdx]['id'])+'\t'+str(gorod)+u'\t'+last_name+'\t'+first_name+u'\t'+mobile_phone+u'\t'+birthday+'\n'
                        try:
                            vivod = vivod.encode("KOI8-R")
                        except:
                            vivod = 'Ошибка пользователя id='+str(response['items'][usdx]['id'])
                        percent = (100.0/kolvo)*indx
                        print('Выполнено:'+str(percent)+'%\t')#+vivod
                        file.write(vivod)
                        telsea=telsea+1		
            file.close
            print('_'*35+relig+'_'*3+'найдено:'+str(telsea)+' это в процентах:'+str(100.0/kolvo*telsea)+'_'*35)
            
vko()


Полученную инфу легко преобразовать в список Id, понятный VkBot и приглашать-приглашать-приглашать.

Поиск топовых новостей
Идея: из ленты вытаскивать новости с высоким процентом репостов из числа лайков записи. Также показать те новости, где много комментариев. Найденные новости отправлять мне личным сообщением (тогда удобно просматривать и репостить)
# -*- coding: utf-8 -*-
import vk_api
import time
import re

def bestWall(vk, popul, query):   
    count=200    
    q=popul+" "+query    
    values = {'q':q, 'count': count}
    response = vk.method('newsfeed.search', values)

    a="репосты"+"\n"+q+"\n"
    b="комменты"+"\n"+q+"\n"
    nayd=0
    for i in range(len(response['items'])):
        likes=response['items'][i]['likes']['count']+1
        reposts=response['items'][i]['reposts']['count']
        comments=response['items'][i]['comments']['count']
        owner_id = response['items'][i]['owner_id']
        id = response['items'][i]['id']
        
        percent=100*reposts/likes
        if percent>45:
            link="http://vk.com/wall"+str(owner_id)+"_"+str(id)
            a=a+link+", "+str(percent)+"%\n"
            nayd=1+nayd
        
        percentComment=100*comments/likes
        if (percent>20)&(comments>100):
            link="http://vk.com/wall"+str(owner_id)+"_"+str(id)
            b=b+link+", "+str(percent)+"%\n"
            nayd=1+nayd
    return a+"\n"+b
            
def bestWallAll(query,vk):
    popul="likes:10"
    a = bestWall(vk, popul, query)
    popul="likes:100"
    b = bestWall(vk, popul, query)
    popul="likes:1000"
    c = bestWall(vk, popul, query)
    all=a+"\n"+b+"\n"+c+"\n"
    return  all
    
        

login = 111#Логин от ВК
password = 222#Пароль от ВК

try:
    vk = vk_api.VkApi(login, password)  # Авторизируемся
except vk_api.authorization_error as error_msg:
    print(error_msg)  # В случае ошибки выведем сообщение
    return  # и выйдем

# query="Апостол"
# query="Лесков"
# query="Евангелие"
# query="доброта"
# query="молитва"
# query="старец"
# query="достоевский"
# query="патриарх Кирилл"
# query="Петр Мамонов"
# query="православие"
query="Шевкунов"

messaga = bestWallAll(query,vk)
values = {'user_id':2945428, 'message': messaga}
response = vk.method('messages.send', values)

print "готово!"


Думаю, что пока этого хватить. Итак уже хабр нагрузился.
Что же из всего этого получилось?

Запускаем -> достигаем


  1. Число участников увеличилось, но за месяц работы мне не удалось увеличить количество в два раза


  2. Ура! Среднесуточное посещение более 100 человек в день.
  3. Повысить качество записей на стене группы относительно удалось. Виден рост, но при «отпускании» группы — отклик посетителей уменьшается

  4. Минимизировать свои трудозатраты


Нет предела совершенству


Сейчас хочу запуск всех скриптов собрать в одном gui интерфейсе, прототип которого можно увидеть на видео.

В планах захомутать facebook, одноклассники и мой мир. Но руки пока не дошли.

Спасибо за внимание.