Creating .exe file for authorization and interaction with VK API using Python

In this article, we will consider a way to create an .exe file that allows you to go through VK authorization and fulfill certain requests to the VK API. Python installation is not required.

System requirements

Background and, in fact, why did I need it

About a year ago, I came across a public engaged in translating foreign articles into Russian.

After some time, the idea came up to create a page on which all-all-all translations will be categorized. And, of course, this page will need to be updated occasionally, i.e. collect information about already released materials, their categories, etc., and then lay them on the shelves. In general, VK API allows you to do this.

But that’s not all: every participant with editorial rights should also be able to update all pages. The way to "get these humanities of all editors to install python for themselves" obviously does not work. You just need to - click, click, start, earn, close. Simply put, you need a .exe file.

Moreover, if you add code that interacts with a specific user to the file body, you can create, for example, a universal audio sorter .

Perhaps the method outlined here is another invented bicycle, but still I will continue.

Step zero. Training

In the folder where our future files will be stored, create a subfolder (for example, bin), where we save chromedriver.exe, cacert.pem and (if you really want to) an icon for our future .exe file. In the same folder we place the empty text file path_to_chrome.txt for now .

Step one. Login

So, everything is ready. Once again about how the process of authorization and obtaining the access key access_token for working with the API occurs .

  1. The user follows the link, the application requests access
  2. User Grants Access
  3. A redirect to a  blank page occurs: access_token appears in the address bar

How the link is formed is described in the official documentation .

We import everything we need, declare constants:

import os
import sys
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import vk
from script import PagesUpdater
SCOPE = 'pages'  #
OAUTH = '{}\
IDLE = 3
TOKEN = 'access_token='  # после этого следует сам access_token
ATOKEN_LEN = 85          # и его длина — 85 символов
CHROME_DRIVER = '\chromedriver.exe'
PATH = os.getcwd()
PATH_TO_CHROME_TXT = PATH + '\path_to_chrome.txt'
class Executor(object):
    def launch(self):
        chrome_path = self.get_chrome_path()
        self.driver = webdriver.Chrome(chrome_path)  # запуск selenium
        access_token = self.get_access_token()
        vkapi = vk.API(access_token=access_token)    # запуск API
        script = PagesUpdater(vkapi, vk.api.VkAPIMethodError, self.driver)

About  PagesUpdater and referred to it the arguments will be discussed later.

Selenium requires you to specify the full path to the chromedriver.exe file, which should be in the same folder with the browser. The browser path is probably different on each computer, so we’ll put it in a separate text file path_to_chrome.txt with the following contents:


    def get_chrome_path(self):
        with open(PATH_TO_CHROME_TXT, 'r') as target:

Of course, the user must specify the full path to the browser in path_to_chrome.txt in  advance .

We intercept access_token:

    def get_access_token(self):
        self.driver.get(OAUTH)  # открыть ссылку для получения ключа
        access_token = ''
        while not access_token:
            page_url = self.driver.current_url
            if TOKEN in page_url:
                token_start = page_url.index(TOKEN) + len(TOKEN)
                access_token = page_url[token_start:token_start+ATOKEN_LEN]
        return access_token

Well, finally, looking ahead, I’ll say that after compilation an error occurs due to the lack of the cacert.pem file . Here's the solution: add cacert.pem to PATH, and then remember to build .exe when building it:

def resource_path(relative):
    return os.path.join(getattr(sys, '_MEIPASS', os.path.abspath(".")),
cert_path = resource_path('cacert.pem')
os.environ['REQUESTS_CA_BUNDLE'] = cert_path

Finishing touch.
exe = Executor()

All. Move on.

Step Two We turn to VK API

Again, we import everything we need, declare constants:

import requests
import time
CAPTCHA_IMG = 'captcha_img'
CAPTCHA_SID = 'captcha_sid'
class PagesUpdater(object):
    def __init__(self, vkapi, vkerror, driver):
        self.vkapi = vkapi
        self.vkerror = vkerror
        self.driver = driver

self.vkapi will be used to access any VK API methods. Two other arguments will be used to handle Captcha (see below).

Error processing

I came across three errors that were guaranteed to appear with a large number of requests:

  1. VK Captcha Error (no text entered from the Captcha image)
  2. VK Flood Control (too many requests per second)
  3. requests.exceptions.Timeout (appears whenever she wants)

Let's create a method in which we will "wrap" all requests to the VK API:

    def errors(self, vkmethod, **vkkwargs):
        while True:
                time.sleep(LIMIT)  # LIMIT == 1 just in case
                return vkmethod(**vkkwargs)
            except requests.exceptions.Timeout:

The second and third errors were sorted out:

  • Before each request there will be a second delay (more about requests in  the documentation ).
  • If requests.exceptions.Timeout occurs, the request will simply be repeated

With Captcha, things are a little more complicated. Read the documentation :
... you should ask the user to enter text from the captcha_img image and repeat the request by adding parameters to it:

  • captcha_sid  - received identifier
  • captcha_key  - text entered by the user

Add an except block in which Captcha will be processed:

            except self.vkerror as e:
                if CAPTCHA_IMG in e.error:
                    self.driver.get(e.error[CAPTCHA_IMG])  # открыть картинку
                    key = raw_input(R)                     # ввести код
                    vkkwargs[captcha_sid] = e.error[CAPTCHA_SID]
                    vkkwargs[captcha_key] = key            # повторить запрос
                    raise  # если же ошибка не в Captcha

We sorted out the errors. Move on.

API request

Add a simple method that returns a list of wiki pages in a group:

    def get_titles(self, gid=NGID):
        return self.errors(self.vkapi.pages.getTitles,

And the launch method , in which everything else will happen:

    def launch(self):
        print self.get_titles()
        # do something else

That's all.

Compilation in .exe

It remains only to run the file with the following code:

import os
import sys
from distutils.core import setup
import py2exe
AUTHOR = 'Варвара Холодная'
COMPANY = 'ООО «Контора»'
NAME = 'Имя будущего .exe файла'
DESCRIPTION = 'Описание файла'
BIN = 'bin/'
# файлы, которые нужно будет собрать из папки bin
    'path_to_chrome.txt', 'cacert.pem', 'chromedriver.exe'
        'py2exe': {
            'bundle_files': 1,
            'compressed': True,
            'unbuffered': True,
            'optimize': 0,
    data_files=[('', [BIN+s for s in DATA_FILES])],
        'script': SCRIPT,
        'name': NAME,
        'dest_base': NAME,
        'description': DESCRIPTION,
        'copyright': AUTHOR,
        'company_name': COMPANY,
        'version': VERSION

After successful compilation, the dist folder will appear, in which all the necessary files will be located.


Testing files with manual authorization is inconvenient. It is much easier to go through the OAuth link yourself, write out access_token and then execute another file, for example, (of course, it will not be suitable for transfer to another user):

import vk
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from script import PagesUpdater
ACCESS_TOKEN = 'Заранее полученный и сохраненный access_token'
VKAPI = vk.API(access_token=ACCESS_TOKEN)
VKError = vk.api.VkAPIMethodError
class DirectUpdater(PagesUpdater):
    def __init__(self, driver_path):
        self.vkapi = VKAPI
        self.vkerror = VKError
        self.driver = webdriver.Chrome(driver_path)
du = DirectUpdater(
    'Путь к chromedriver.exe')

Also popular now: