from googleapiclient.discovery import build
from google.oauth2 import service_account
# Укажите путь к скачанному JSON-файлу сервисного аккаунта
SERVICE_ACCOUNT_FILE = 'ваш_сервис_аккаунт_файл.json'
# Настройка доступа
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE,
scopes=['https://www.googleapis.com/auth/spreadsheets'])
service = build('sheets', 'v4', credentials=credentials)
def update_note(spreadsheet_id, sheet_name, cell, note_text):
# Конвертация имени ячейки в индексы:
col = ord(cell[0].upper()) - ord('A')
row = int(cell[1:]) - 1
# Получаем ИД листа:
spreadsheet = service.spreadsheets().get(
spreadsheetId=spreadsheet_id,
fields="sheets(properties(sheetId,title))"
).execute()
sheetId = [sheet['properties']['sheetId'] for sheet in spreadsheet['sheets'] if
sheet['properties']['title'] == sheet_name][0]
print(sheetId)
service.spreadsheets().batchUpdate(
spreadsheetId=spreadsheet_id,
body={
"requests": [{
"updateCells": {
"range": {
"sheetId": sheetId,
"startRowIndex": row,
#"endRowIndex": row + 1,
"startColumnIndex": col,
#"endColumnIndex": col + 1
},
"rows": [{"values": [{"note": note_text}]}],
"fields": "note"
}
}]
}
).execute()
# Использование:
spreadsheetId = 'ваш ид таблицы'
update_note(spreadsheetId, "Лист3", "B3", "Тестовое примечание.")
def read_note(spreadsheet_id, sheet_name, cell) -> str or None:
response = service.spreadsheets().get(
spreadsheetId=spreadsheet_id,
ranges=[f"{sheet_name}!{cell}"],
fields='sheets(data.rowData.values.note)'
).execute()
note = (response
.get('sheets', [{}])[0]
.get('data', [{}])[0]
.get('rowData', [{}])[0]
.get('values', [{}])[0]
.get('note'))
return note
# Использование:
spreadsheetId = 'ваш ид таблицы'
read_note(spreadsheetId, 'Лист3', 'B3')
def get_db_path():
if getattr(sys, 'frozen', False):
# Если запущен из .exe, использовать путь рядом с исполняемым файлом
return os.path.join(os.path.dirname(sys.executable), 'database.db')
else:
# При обычном запуске — рядом с .py файлом
return os.path.join(os.path.dirname(__file__), 'database.db')
pyinstaller --onefile --windowed app.py
pyinstaller --onefile --add-data "database.db;." --windowed app.py
things = ['Thing one','Thing two','Thing three']
nl = '\n'
print(f"I have a list of things:\n{nl.join(things)}")
perf_counter()
из модуля time
. import pyshark
display_filter = 'tls.record.content_type == 22'
pcap = pyshark.FileCapture(file_path, display_filter=display_filter)
d = {}
for packet_number, packet in enumerate(pcap):
for layer in packet:
if 'Supported Version:' in str(layer):
for line in str(layer).splitlines():
if 'Supported Version:' in line:
tls_version = line.split(' ')[3]
if packet_number in d:
d[packet_number].append(tls_version)
else:
d[packet_number] = [tls_version]
print(d)
>>> {0: ['1.3', '1.2'], 1: ['1.3'], 2: ['1.3', '1.2'], 3: ['1.3'], 4: ['1.3', '1.2'], 5: ['1.3']}
import re
s = "57-09-71 МегаФонe-mail: ? vy:juf , h 5555y676hr965 silava.a@ttgr : https://loads.ru"
url_pattern = r'https?://\S+'
url_match = re.search(url_pattern, s)
if url_match:
url = url_match.group(0)
print(url)
else:
print("Ссылка не найдена")
>>> https://loads.ru
print(s.split(' ')[-1])
start_time
заведомо "меньше", чем server_time
, а вы вычитаете из меньшего большее, то и возникает разница в -1 день. abs
при подсчёте дельты:from datetime import datetime, timezone
start_time = datetime(2025, 1, 27, 23, 59, 59, tzinfo=timezone.utc)
server_time = datetime(2025, 1, 28, 0, 0, 0, tzinfo=timezone.utc)
delta = start_time - server_time
print("Дельта:", delta)
>>> Дельта: -1 day, 23:59:59
abs_delta = abs(start_time - server_time)
print("Дельта:", abs_delta)
>>> Дельта: 0:00:01
SORT_BUTTON = (By.XPATH, "(//span[@class='select2-selection select2-selection--single select2-selection--buttoned select2-selection--buttoned-dark select select--sorting'])[1]")
SORT_ASC_OPTION = (By.ID, 'select2-catalog_sorting_mobile-7h-result-jsvp-price:asc')
SORT_DESC_OPTION = (By.ID, 'select2-catalog_sorting_mobile-7h-result-jsvp-price:desc')
def select_sort_option()
добавил небольшую задержку (2-3 секунды) после WebDriverWait(self.driver, 10).until(EC.staleness_of(option))
. [...11900, 11900, 7735, 11900...],
что никак не будет равно отсортированному списку цен в assert
.test_sort_by_price[\u0426\u0435\u043d\u0430 \u043f\u043e \u0432\u043e\u0437\
,[pytest]
disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True
import requests
from bs4 import BeautifulSoup
def parse_table(div, results):
# Ищем таблицы внутри данного div
tables = div.find_all('table')
for table in tables:
rows = table.find_all('tr')
for row in rows:
cells = row.find_all('td')
if cells:
# Извлекаем название и ссылку
name = cells[0].get_text(strip=True)
link = cells[0].find('a')['href'] if cells[0].find('a') else None
if link:
results[name] = link
def recursive_parse(url, visited, results):
if url in visited:
return
visited.add(url)
print('Парсим URL:', url)
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# Ищем все div с itemscope
divs = soup.find_all('div', itemscope=True)
for div in divs:
parse_table(div, results) # Парсим таблицы внутри найденного div
# Ищем все ссылки на подстраницы
links = soup.find_all('a', href=True)
for link in links:
sub_url = link['href']
# Проверяем, что ссылка ведет на подстраницу и не является текущим URL
if 'respublika_bashkortostan' in sub_url and sub_url.startswith('http') and sub_url != url:
recursive_parse(sub_url, visited, results)
# Начальная URL
start_url = 'https://russiaschools.ru/respublika_bashkortostan/'
visited_urls = set()
results_dict = {}
recursive_parse(start_url, visited_urls, results_dict)
for name, link in results_dict.items():
print(f'Название: {name}, Ссылка: {link}')