📜 ⬆️ ⬇️

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

This article will discuss the way to create an .exe file that allows you to pass authorization VK and perform certain requests to the VK API. Installing Python is not required.

System requirements



Prehistory and, actually, why did I need it


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

After some time, the idea arose to create a page on which all-all-all translations would 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 out on the shelves. In general, the VK API allows you to do this.
')
But this is not all: every member with editorial rights must also be able to update all pages. The way "to force these humanists of all editors to install python for themselves" is obviously not suitable. You just need to - click, click, start, earn, close. Simply put, you need an .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 the chromedriver.exe, cacert.pem and (if you really want) icon for our future .exe file. For the time being, we place an empty text file path_to_chrome.txt in this folder.

Step one. Authorization


So, everything is ready. Once again about how the authorization process and access key access_token to work with the API.

  1. The user follows the link, the application requests access
  2. User allows access
  3. Redirecting 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 the arguments passed to him will be discussed later.

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

 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 catch 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, and finally, looking ahead, I will say that after compilation an error occurs due to a lack of the cacert.pem file. Here is the solution: add cacert.pem to PATH, and then remember to compile it when building .exe:

 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() 

Everything. Go ahead.

Step two. Contact VK API


Again, import everything you 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 refer to any methods of the VK API. The other two arguments will be used to handle Captcha (see below).

Error processing


I encountered three errors that guaranteed to appear with a large number of requests:

  1. VK Captcha Error (no text entered from Captcha image)
  2. VK Flood Control (too many requests per second)
  3. requests.exceptions.Timeout (appears when it pleases)

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 

With the second and third errors figured out:


With Captcha, everything is a little more complicated. We read documentation :
... you should ask the user to enter the text from the image captcha_img and repeat the request, adding parameters to it:

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

Add except the block in which the Captcha processing will occur:

  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 

Deal with mistakes. Go ahead.

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 

Actually, that's all.

Compile 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 folder dist will appear, in which all necessary files will be located.

PS


Testing files with manual authorization is inconvenient. It is much easier to follow the OAuth link, write access_token and then execute another file, for example, auth_direct.py (of course, it is not 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() 

Source: https://habr.com/ru/post/269245/


All Articles