from PIL import Image from io import BytesIO from selenium.webdriver.common.actions.wheel_input import ScrollOrigin from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from time import sleep import constants import cv2 import math import numpy as np import os import utility def generateURL(lat: float, lon: float, zoom: int): return f"https://yandex.ru/maps/43/kazan/?l=sat&ll={lat}%2C{lon}&z={zoom}" class YandexMap: initial_zoom: int initial_lat: float initial_lon: float def __init__(self, initial_lat=49.103814, initial_lon=55.794258, initial_zoom=10): self.initial_lat = initial_lat self.initial_lon = initial_lon self.initial_zoom = initial_zoom self.pixel_ratio = constants.YANDEX_PIXEL_RATIO[self.initial_zoom] options = webdriver.ChromeOptions() # options.add_experimental_option("detach", True) self.driver = webdriver.Chrome(options) self.driver.get(generateURL(initial_lat, initial_lon, initial_zoom)) self.driver.maximize_window() sleep(2) # Закрытие левой панели action = ActionChains(self.driver) action.click(self.driver.find_element(By.CLASS_NAME, 'sidebar-toggle-button')) action.perform() self.driver.execute_script("arguments[0].remove();", self.driver.find_element(By.XPATH, "//div[@data-chunk='header']")) self.driver.execute_script("arguments[0].remove();", self.driver.find_element(By.XPATH, "//div[@class='sidebar-toggle-button _collapsed _name_home']")) self.driver.execute_script("arguments[0].remove();", self.driver.find_element(By.XPATH, "//nav[@class='map-controls']")) self.driver.execute_script("arguments[0].remove();", self.driver.find_element(By.XPATH, "//footer")) self.move(39, -9) sleep(0.2) def open(self, lat, lon, zoom): self.initial_lat = lat self.initial_lon = lon self.initial_zoom = zoom self.pixel_ratio = constants.YANDEX_PIXEL_RATIO[self.initial_zoom] self.driver.get(generateURL(lat, lon, zoom)) sleep(2) # Закрытие левой панели action = ActionChains(self.driver) action.click(self.driver.find_element(By.CLASS_NAME, 'sidebar-toggle-button')) action.perform() self.move(39, -9) def save_photo(self, filename: str) -> bytes: return self.driver.save_screenshot(filename) def destroy(self): self.driver.close() def get_size(self) -> tuple[int, int]: html = self.driver.find_element(By.TAG_NAME, 'html') return (html.size['width'], html.size['height']) def scroll(self, x: float, y: float, count: int = 1, inner_zoom: bool = True): html = self.driver.find_element(By.TAG_NAME, 'html') x_offset = (x - 0.5) * html.size['width'] y_offset = (y - 0.5) * html.size['height'] action = ActionChains(self.driver) for i in range(count-1): action.scroll_from_origin(ScrollOrigin(html, int(x_offset), int(y_offset)), 0, -100 if inner_zoom else 100) action.perform() if i != count - 1: sleep(0.25) def move(self, dx: float, dy: float): html = self.driver.find_element(By.TAG_NAME, 'html') action = ActionChains(self.driver) action.move_to_element_with_offset(html, 0, 0) action.click_and_hold() action.move_by_offset(-dx, dy) action.release() action.perform() def make_as_center(self, x: float, y: float): dx = (x - 0.5) * self.get_size()[0] dy = (0.5 - y) * self.get_size()[1] self.move(dx, dy) def make_screenshot(self) -> Image.Image: png = self.driver.get_screenshot_as_png() im = Image.open(BytesIO(png)) return utility.cv2_to_pil(np.array(im)[:, :]) def get_geolocation(self): current_url = self.driver.current_url return utility.parse_yandex_maps_url(current_url)