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.
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 "getthese 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.
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 .
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 .
How the link is formed is described in the official documentation .
We import everything we need, declare constants:
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:
Of course, the user must specify the full path to the browser in path_to_chrome.txt in advance .
We intercept 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:
Finishing touch.
All. Move on.
Again, we import everything we need, declare constants:
self.vkapi will be used to access any VK API methods. Two other arguments will be used to handle Captcha (see below).
I came across three errors that were guaranteed to appear with a large number of requests:
Let's create a method in which we will "wrap" all requests to the VK API:
The second and third errors were sorted out:
With Captcha, things are a little more complicated. Read the documentation :
Add an except block in which Captcha will be processed:
We sorted out the errors. Move on.
Add a simple method that returns a list of wiki pages in a group:
And the launch method , in which everything else will happen:
That's all.
It remains only to run the file with the following code:
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, auth_direct.py (of course, it will not be suitable for transfer to another user):
System requirements
- Windows
- Browser (based on Chromium)
- Python, py2exe and Selenium
- Application for working with VK API
- Files cacert.pem and chromedriver.exe
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
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 .
- The user follows the link, the application requests access
- User Grants Access
- 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' # vk.com/dev/permissions
OAUTH = 'https://oauth.vk.com/authorize?client_id=4836475&scope={}\
&redirect_uri=https://oauth.vk.com/blank.html&display=popup&v=5.37\
&response_type=token'.format(SCOPE)
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)
script.launch()
self.driver.quit()
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:
C:\chrome-win32\chrome-win32
def get_chrome_path(self):
with open(PATH_TO_CHROME_TXT, 'r') as target:
return target.read()
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]
break
else:
time.sleep(IDLE)
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(".")),
relative)
cert_path = resource_path('cacert.pem')
os.environ['REQUESTS_CA_BUNDLE'] = cert_path
Finishing touch.
exe = Executor()
exe.launch()
All. Move on.
Step Two We turn to VK API
Again, we import everything we need, declare constants:
import requests
import time
LIMIT = 1
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:
- VK Captcha Error (no text entered from the Captcha image)
- VK Flood Control (too many requests per second)
- 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:
try:
time.sleep(LIMIT) # LIMIT == 1 just in case
return vkmethod(**vkkwargs)
except requests.exceptions.Timeout:
continue
break
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 # повторить запрос
continue
else:
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,
group_id=gid)
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
sys.argv.append('py2exe')
AUTHOR = 'Варвара Холодная'
COMPANY = 'ООО «Контора»'
NAME = 'Имя будущего .exe файла'
DESCRIPTION = 'Описание файла'
SCRIPT = 'auth_user.py'
VERSION = '1.0.0.0'
BIN = 'bin/'
# файлы, которые нужно будет собрать из папки bin
DATA_FILES = [
'path_to_chrome.txt', 'cacert.pem', 'chromedriver.exe'
]
setup(
options={
'py2exe': {
'bundle_files': 1,
'compressed': True,
'unbuffered': True,
'optimize': 0,
}
},
data_files=[('', [BIN+s for s in DATA_FILES])],
console=[{
'script': SCRIPT,
'name': NAME,
'dest_base': NAME,
'description': DESCRIPTION,
'copyright': AUTHOR,
'company_name': COMPANY,
'version': VERSION
}],
zipfile=None,
)
After successful compilation, the dist folder will appear, in which all the necessary files will be located.
PS
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, auth_direct.py (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')
du.launch()