напиши код на Phyton, который будет брать данные и...
Создано: 29 мая 2025 г.
Создано: 29 мая 2025 г.
напиши код на Phyton, который будет брать данные из таблицы Excell и вставлять их в строку поиска на конкретном сайте, далее запускать поиск. Результат - фраза в конкретном месте страницы сайта, ее нужно скопировать и вставить результат в столбец таблицы Excell, рядом с тем из которого формировался запрос. Если нужна дополнительная информация, задавай
Конечно! Чтобы написать скрипт, мне понадобится чуть‑чуть конкретики о вашем рабочем процессе. Подскажите, пожалуйста:
Сайт и его элементы
* URL страницы, на которой находится поле поиска.
* Какое именно поле нужно заполнять: его id
, name
, CSS‑селектор или XPath.
* После ввода запроса надо нажать кнопку? Если да, дайте селектор кнопки (или уточните, что поиск запускается по Enter).
* Где точно на странице появляется фраза‑результат? Лучше всего — CSS‑селектор/XPath к нужному элементу.
Файл Excel
* Имя (или полный путь) файла.
* Название листа (если не указать, возьму первый).
* В какой колонке лежат запросы? (буква/заголовок, например A
или query
).
* В какой колонке нужно записать результат? Создать новую («Result») или использовать существующую?
Технические ограничения
* Нужен ли прокси/авторизация на сайте?
* Ну и, на всякий случай: какую версию Python/W‑пакетов вы сможете установить? (В примере я собираюсь использовать pandas
, openpyxl
и selenium
.)
Как только получу эти детали, пришлю готовый шаблон кода: чтение Excel → Selenium‑поиск → парсинг результата → запись обратно в Excel.
https://lynxauto.info/
найди на этой странице поле для заполнения, в этом поле написано "Универсальный поиск: введите любой номер или марку автомобиля" и отправь мне его id, name, CSS‑селектор или XPath.
https://lynxauto.info/BD-2847.html
Так же найти на этой странице фразу "BD-2847" и отправь мне его id, name, CSS‑селектор или XPath.
Вот что можно «достать» из страницы, не исполняя её JavaScript, и какие надёжные селекторы обычно используют для работы через Selenium:
Задача | Надёжный CSS-селектор | Эквивалентный XPath | Комментарий |
---|---|---|---|
Поле «Универсальный поиск» на https://lynxauto.info/ | input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля'] | //input[@placeholder='Универсальный поиск: введите любой номер или марку автомобиля'] | На сайте поле выводится динамически JS-кодом, поэтому атрибутов id /name в статической разметке нет; placeholder — самое надёжное, за него «цепляйтесь». |
Текст «BD-2847» на странице товара …/BD-2847.html | (CSS-селектор по тексту в Selenium не поддерживается) | //h1[contains(normalize-space(),'BD-2847')] | Код детали выводится как заголовок <h1> ; точный id или class в статике опять же не виден, поэтому XPath по тексту — самый простой и устойчивый способ. |
pythonfrom selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.get("https://lynxauto.info/") # --- Универсальный поиск --- search_box = driver.find_element(By.CSS_SELECTOR, "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']") search_box.send_keys("BD-2847") search_box.submit() # или клик по кнопке, если нужно # --- Страница результата --- driver.get("https://lynxauto.info/BD-2847.html") code_h1 = driver.find_element(By.XPATH, "//h1[contains(normalize-space(),'BD-2847')]") print(code_h1.text)
Важно: если в вашей установке Selenium не находит элементы сразу после загрузки, добавьте
WebDriverWait
сEC.presence_of_element_located
, потому что обе страницы полностью «рисуются» скриптами.
https://lynxauto.info/ сайт где находится строка поиска
CSS селектор строки поиска - input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']
X-path строки поиска - input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']
Поиск активируется нажатием "ENTER"
после запуска поиска ты перейдешь на страницу с результатом
input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля'] - X-path результата
C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx - путь к таблице Excell
В колонке "C" лежат запросы
Полученный результат вставлять в столбец "H" в ту же строку, из которой берешь запрос например "Запрос находится в C2, результат записать в H2"
Если после выполненного поиска ты получишь неизвестный тебе результат, в столбце с результатами напиши "Ошибка".
Прокси и авторизация на сайте на нужны.
Так же мне нужна возможность ограничивать количество запросов в час, что бы не перегружать сайт.
Могу установить любые пакеты Phyton, напиши какие тебе нужны
Ниже — готовый минимальный скрипт Python:
https://lynxauto.info/
, вводит запрос в поле поискаinput[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']
,<h1>
(на товарной странице это и есть код детали);MAX_REQUESTS_PER_HOUR
(по‑умолчанию 50).python""" LynxAuto → Excel updater ----------------------------------- • Excel : C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx • Queries : column C (first worksheet) • Results : column H • Site : https://lynxauto.info/ ----------------------------------- """ from pathlib import Path import time import math import pandas as pd from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ── настройте под себя ───────────────────────────────────────────────────────── EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") SHEET_NAME = None # None = первый лист QUERY_COLUMN_LETTER = "C" RESULT_COLUMN_LETTER = "H" MAX_REQUESTS_PER_HOUR = 50 # лимит нагрузки на сайт HEADLESS = False # True — если нужен фоновый режим TIMEOUT = 15 # секунд ожидания элементов # ─────────────────────────────────────────────────────────────────────────────── URL = "https://lynxauto.info/" SEARCH_BOX_CSS = "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']" RESULT_XPATH = "//h1" # код детали отображается как <h1>…</h1> PAUSE = 3600 / MAX_REQUESTS_PER_HOUR def setup_driver(headless: bool = False) -> webdriver.Chrome: options = webdriver.ChromeOptions() if headless: options.add_argument("--headless=new") # Chrome >=118 service = Service(ChromeDriverManager().install()) return webdriver.Chrome(service=service, options=options) def fetch_result(driver: webdriver.Chrome, query: str) -> str: """Вводит запрос, возвращает текст <h1> или 'Ошибка'.""" try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) box = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, SEARCH_BOX_CSS))) box.clear() box.send_keys(query) box.send_keys(Keys.ENTER) h1 = wait.until(EC.presence_of_element_located((By.XPATH, RESULT_XPATH))) text = h1.text.strip() return text if text else "Ошибка" except Exception: return "Ошибка" def main() -> None: # ── читаем Excel в DataFrame ─────────────────────────────────────────────── df = pd.read_excel(EXCEL_FILE, sheet_name=SHEET_NAME, dtype=str) # заполняем колонку результатов, если её ещё нет if RESULT_COLUMN_LETTER not in df.columns: df.insert(loc=len(df.columns), column=RESULT_COLUMN_LETTER, value="") driver = setup_driver(headless=HEADLESS) try: for idx, row in df.iterrows(): query = str(row.get(QUERY_COLUMN_LETTER, "")).strip() if not query or query.lower() == "nan": continue start = time.perf_counter() result = fetch_result(driver, query) df.at[idx, RESULT_COLUMN_LETTER] = result print(f"{idx+2}: {query} → {result}") # пауза, чтобы не превысить лимит elapsed = time.perf_counter() - start to_sleep = max(0, PAUSE - elapsed) if to_sleep: time.sleep(to_sleep) finally: driver.quit() # ── пишем обновлённый DF обратно в тот же файл ──────────────────────────── wb = load_workbook(EXCEL_FILE) ws = wb[SHEET_NAME or wb.sheetnames[0]] for r_idx, (_, row) in enumerate(df.iterrows(), start=2): # 2 — потому что Excel‑заголовок в 1‑й строке ws[f"{RESULT_COLUMN_LETTER}{r_idx}"].value = row[RESULT_COLUMN_LETTER] wb.save(EXCEL_FILE) print("✔ Готово!") if __name__ == "__main__": main()
bashpip install pandas openpyxl selenium webdriver-manager
(При необходимости добавьте pip install tqdm
— если поставите индикатор прогресса.)
Убедитесь, что установлен Google Chrome; webdriver-manager
сам подберёт подходящий chromedriver.
Измените значение MAX_REQUESTS_PER_HOUR
, если нужно иное ограничение, или задайте HEADLESS = True
, чтобы скрипт работал без открывающегося окна браузера.
Запустите:
bashpython lynx_to_excel.py
<h1>
;При необходимости уточнить, например, точный XPath результата (если понадобится не <h1>
, а другое место), дайте знать — подправим один‑единственный локатор в переменной RESULT_XPATH
.
SyntaxError: invalid syntax
выдаёт ошибку
pythonscript = """ from pathlib import Path import time import math import pandas as pd from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC EXCEL_FILE = Path(r"C:\\Users\\s.akaemov\\Desktop\\Проверка кроссов код.xlsx") SHEET_NAME = None QUERY_COLUMN_LETTER = "C" RESULT_COLUMN_LETTER = "H" MAX_REQUESTS_PER_HOUR = 50 HEADLESS = False TIMEOUT = 15 URL = "https://lynxauto.info/" SEARCH_BOX_CSS = "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']" RESULT_XPATH = "//h1" PAUSE = 3600 / MAX_REQUESTS_PER_HOUR def setup_driver(headless: bool = False) -> webdriver.Chrome: options = webdriver.ChromeOptions() if headless: options.add_argument("--headless=new") service = Service(ChromeDriverManager().install()) return webdriver.Chrome(service=service, options=options) def fetch_result(driver: webdriver.Chrome, query: str) -> str: try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) box = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, SEARCH_BOX_CSS))) box.clear() box.send_keys(query) box.send_keys(Keys.ENTER) h1 = wait.until(EC.presence_of_element_located((By.XPATH, RESULT_XPATH))) text = h1.text.strip() return text if text else "Ошибка" except Exception: return "Ошибка" def main() -> None: df = pd.read_excel(EXCEL_FILE, sheet_name=SHEET_NAME, dtype=str) if RESULT_COLUMN_LETTER not in df.columns: df.insert(loc=len(df.columns), column=RESULT_COLUMN_LETTER, value="") driver = setup_driver(headless=HEADLESS) try: for idx, row in df.iterrows(): query = str(row.get(QUERY_COLUMN_LETTER, "")).strip() if not query or query.lower() == "nan": continue start = time.perf_counter() result = fetch_result(driver, query) df.at[idx, RESULT_COLUMN_LETTER] = result print(f"{idx+2}: {query} → {result}") elapsed = time.perf_counter() - start to_sleep = max(0, PAUSE - elapsed) if to_sleep: time.sleep(to_sleep) finally: driver.quit() wb = load_workbook(EXCEL_FILE) ws = wb[SHEET_NAME or wb.sheetnames[0]] for r_idx, (_, row) in enumerate(df.iterrows(), start=2): ws[f"{RESULT_COLUMN_LETTER}{r_idx}"].value = row[RESULT_COLUMN_LETTER] wb.save(EXCEL_FILE) print("✔ Готово!") if __name__ == "__main__": main() """ import ast, textwrap, sys, traceback, types, importlib compile(script, filename="<test>", mode='exec') <code object <module> at 0x7ecebb45f000, file "<test>", line 1>
Хочу разобраться, где именно падает парсер.
Пожалуйста, скопируйте полностью сообщение об ошибке — 2-3 строки до слова SyntaxError и 2-3 после. Важны:
File "...", line N
)python --version
)Так я пойму, нужно ли убрать тип-аннотации, заменить какой-то символ или, например, добавить строку # -*- coding: utf-8 -*-
в начале файла.
1 """"""
2 LynxAuto → Excel updater
3-----------------------------------
4• Excel : C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx
5• Queries : column C (first worksheet)
6• Results : column H
7• Site : https://lynxauto.info/
8-----------------------------------
9"""
Ругается с 2 по 8 строки
Phyton 3.13.3
22 from selenium.webdriver.support import expected_conditions as EC
23
24 ── настройте под себя ─────────────────────────────────────────────────────────
25 EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx")
26 SHEET_NAME = None # None = первый лист
27 QUERY_COLUMN_LETTER = "C"
ругается на строку 25 на фрагмент /Users
45
46 def fetch_result(driver: webdriver.Chrome, query: str) -> str:
47 """Вводит запрос, возвращает текст <h1> или 'Ошибка'."""
48 try:
49 driver.get(URL)
ругается на строку 47 Вводит запрос, возвращает текст <h1> или
98 if name == "main":
99 main()ame__ == "main":
100 pip install pandas openpyxl selenium webdriver-manager
Ругается на всю строку 100
pythonprint(r"\Users")
Проблема не в Python, а в том, что в файл попали строки-комментарии без символа #
и посторонний текст (строка pip install …
). Из-за этого интерпретатор пытается выполнить их как код и, естественно, получает SyntaxError
.
Ниже - “чистый” вариант того же скрипта.
#
.if __name__ == "__main__": main()
.Сохраните его, например, как lynx_to_excel.py в UTF-8 (BOM не нужен) и запустите.
python# -*- coding: utf-8 -*- """ LynxAuto → Excel updater ----------------------------------- Excel file : C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx Queries : column C (first worksheet) Results : column H Site : https://lynxauto.info/ ----------------------------------- """ from pathlib import Path import time import pandas as pd from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ------------------------------ SETTINGS ------------------------------------- EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") SHEET_NAME = None # None = first sheet QUERY_COLUMN_LETTER = "C" RESULT_COLUMN_LETTER = "H" MAX_REQUESTS_PER_HOUR = 50 # throttle HEADLESS = False # True → run browser in background TIMEOUT = 15 # seconds to wait for an element # ----------------------------------------------------------------------------- URL = "https://lynxauto.info/" SEARCH_BOX_CSS = "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']" RESULT_XPATH = "//h1" # <h1> contains the code on result page PAUSE = 3600 / MAX_REQUESTS_PER_HOUR def setup_driver(headless: bool = False) -> webdriver.Chrome: options = webdriver.ChromeOptions() if headless: options.add_argument("--headless=new") # Chrome ≥118 service = Service(ChromeDriverManager().install()) return webdriver.Chrome(service=service, options=options) def fetch_result(driver: webdriver.Chrome, query: str) -> str: """Enter query, return <h1> text or 'Ошибка'.""" try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) box = wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, SEARCH_BOX_CSS)) ) box.clear() box.send_keys(query) box.send_keys(Keys.ENTER) h1 = wait.until(EC.presence_of_element_located((By.XPATH, RESULT_XPATH))) text = h1.text.strip() return text if text else "Ошибка" except Exception: return "Ошибка" def main() -> None: # --- read Excel --- df = pd.read_excel(EXCEL_FILE, sheet_name=SHEET_NAME, dtype=str) if RESULT_COLUMN_LETTER not in df.columns: df.insert(loc=len(df.columns), column=RESULT_COLUMN_LETTER, value="") driver = setup_driver(headless=HEADLESS) try: for idx, row in df.iterrows(): query = str(row.get(QUERY_COLUMN_LETTER, "")).strip() if not query or query.lower() == "nan": continue t0 = time.perf_counter() result = fetch_result(driver, query) df.at[idx, RESULT_COLUMN_LETTER] = result print(f"{idx + 2}: {query} → {result}") elapsed = time.perf_counter() - t0 time.sleep(max(0, PAUSE - elapsed)) finally: driver.quit() # --- write back to the same Excel file --- wb = load_workbook(EXCEL_FILE) ws = wb[SHEET_NAME or wb.sheetnames[0]] for r_idx, (_, row) in enumerate(df.iterrows(), start=2): # 2 = first data row ws[f"{RESULT_COLUMN_LETTER}{r_idx}"].value = row[RESULT_COLUMN_LETTER] wb.save(EXCEL_FILE) print("✓ Done!") if __name__ == "__main__": main()
Причина | Как проявляется | Как исправить |
---|---|---|
Строки-комментарии без # | SyntaxError в “красивых” линиях, стрелках, надписях | Всегда начинайте комментарии с # , либо убирайте декоративные символы |
Путь C:\Users\… без r -строки | SyntaxError: (unicode error) 'unicodeescape' | Обязательно ставьте r"…" или удваивайте обратные слэши (\\ ) |
Случайно вставили команду pip install … в код | SyntaxError | Команды для терминала держите вне .py -файла |
Сохранение в кодировке ANSI | Ошибка в строках с кириллицей | Сохраняйте файл как UTF-8 |
После того как скрипт заработает, можно:
MAX_REQUESTS_PER_HOUR
, чтобы «тормозить» реже или чаще;HEADLESS = True
, чтобы Chrome не открывался на экране.Если снова появятся ошибки, пришлите их полностью — разберёмся.
Как сохранить в utf-8 в pycharm для windows ?
В PyCharm это делается в два-три клика — и для конкретного файла, и «по-умолчанию» для всех новых.
.py
в редакторе.UTF-8
, Windows-1251
, KOI8-R
и т.п.).После конвертации заголовок вкладки перезагрузится, и внизу снова будет
UTF-8
.
Чтобы новые файлы и все неявно открываемые файлы читались/писались в UTF-8:
UTF-8
UTF-8
UTF-8
(если нужно).\uXXXX
вместо русских букв в .properties
).Теперь любая новая вкладка будет сразу в UTF-8, а старые файлы можно при необходимости вручную «переконвертировать» способом из пункта 1.
Ситуация | Что сделать |
---|---|
Появляется вопрос “Reload from disk?” | Если вы только что сменили кодировку и файл не редактировали, смело жмите Reload. |
Нужно принудительно добавить BOM | Внизу, рядом с кодировкой, кликните ⚙ → “Add BOM” (обычно не требуется — Python корректно читает UTF-8 без BOM). |
Библиотека читает файл неправильно | Укажите кодировку явно: <br>open('file.txt', encoding='utf-8') |
Так ваши .py
-файлы будут в «чистом» UTF-8, и московские кавычки, стрелочки и кириллица перестанут вызывать SyntaxError
.
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 82-83: truncated \UXXXXXXXX escape
при запуске выдал это
Ошибка SyntaxError: (unicode error) 'unicodeescape' …
возникает, когда внутри строкового литерала встречается сочетание \u
или \U
, которое Python пытается распознать как юникод-escape \uXXXX
/ \UXXXXXXXX
.
В вашем случае «опасная» последовательность появилась в док-строке:
python""" Excel file : C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx ^ ^ ← вот эти «\U» и «\s» """
Док-строка — это такой же строковой литерал, и обратные слэши в ней надо экранировать (или сделать её «сырой»).
Поставьте букву r
перед тройными кавычками:
pythonr""" LynxAuto → Excel updater ----------------------------------- Excel file : C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx ... """
r"""…"""
говорит интерпретатору: «ничего не обрабатывай внутри, даже \U
».
python""" Excel file : C:\\Users\\s.akaemov\\Desktop\\Проверка кроссов код.xlsx """
EXCEL_FILE
)Док-строка нужна лишь как комментарий, так что путь можно просто удалить или заменить на «…».
python# -*- coding: utf-8 -*- r""" LynxAuto → Excel updater ----------------------------------- Excel file : C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx Queries : column C Results : column H ----------------------------------- """ ... EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx")
После этого SyntaxError
исчезнет.
К сведению: аналогичная ошибка может всплыть где-угодно, если в обычной строке окажется
\u
/\U
. Для путей в Windows удобно либо:
- писать их как raw-строки
r"C:\Users\..."
,- либо менять слэши на прямые
"C:/Users/..."
,- либо дублировать слэши
"C:\\Users\\..."
.
Поправьте док-строку любым из способов и перезапустите скрипт — он должен стартовать без проблем. Если появятся новые сообщения об ошибках, присылайте их целиком (текст + номер строки) — посмотрим дальше.
исправь эту ошибку в последнем коде
Ниже привожу тот же скрипт, но с исправленной док‑строкой — я сделал её «сырой» (перед """
добавлено r
).
Это полностью устраняет ошибку unicodeescape
, потому что все обратные слэши внутри комментария больше не интерпретируются как \U…
.
python# -*- coding: utf-8 -*- r""" LynxAuto → Excel updater ----------------------------------- Excel file : C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx Queries : column C (first worksheet) Results : column H Site : https://lynxauto.info/ ----------------------------------- """ from pathlib import Path import time import pandas as pd from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ------------------------------ SETTINGS ------------------------------------- EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") SHEET_NAME = None # None = first sheet QUERY_COLUMN_LETTER = "C" RESULT_COLUMN_LETTER = "H" MAX_REQUESTS_PER_HOUR = 50 # throttle (измените при необходимости) HEADLESS = False # True → браузер в фоне TIMEOUT = 15 # секунд ожидания элементов # ----------------------------------------------------------------------------- URL = "https://lynxauto.info/" SEARCH_BOX_CSS = ( "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']" ) RESULT_XPATH = "//h1" # <h1> содержит код детали на странице результата PAUSE = 3600 / MAX_REQUESTS_PER_HOUR def setup_driver(headless: bool = False) -> webdriver.Chrome: options = webdriver.ChromeOptions() if headless: options.add_argument("--headless=new") # Chrome ≥118 service = Service(ChromeDriverManager().install()) return webdriver.Chrome(service=service, options=options) def fetch_result(driver: webdriver.Chrome, query: str) -> str: """Вводит query на сайте, возвращает текст <h1> или 'Ошибка'.""" try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) box = wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, SEARCH_BOX_CSS)) ) box.clear() box.send_keys(query) box.send_keys(Keys.ENTER) h1 = wait.until(EC.presence_of_element_located((By.XPATH, RESULT_XPATH))) text = h1.text.strip() return text if text else "Ошибка" except Exception: return "Ошибка" def main() -> None: # --- читаем Excel --- df = pd.read_excel(EXCEL_FILE, sheet_name=SHEET_NAME, dtype=str) if RESULT_COLUMN_LETTER not in df.columns: df.insert(len(df.columns), RESULT_COLUMN_LETTER, "") driver = setup_driver(headless=HEADLESS) try: for idx, row in df.iterrows(): query = str(row.get(QUERY_COLUMN_LETTER, "")).strip() if not query or query.lower() == "nan": continue t0 = time.perf_counter() result = fetch_result(driver, query) df.at[idx, RESULT_COLUMN_LETTER] = result print(f"{idx + 2}: {query} → {result}") # пауза, чтобы не превысить лимит time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) finally: driver.quit() # --- записываем обратно в тот же Excel --- wb = load_workbook(EXCEL_FILE) ws = wb[SHEET_NAME or wb.sheetnames[0]] for r_idx, (_, row) in enumerate(df.iterrows(), start=2): # 2: первая строка данных ws[f"{RESULT_COLUMN_LETTER}{r_idx}"].value = row[RESULT_COLUMN_LETTER] wb.save(EXCEL_FILE) print("✓ Done!") if __name__ == "__main__": main()
r""" … """
— превратило док‑строку в «raw string», поэтому \U
внутри пути больше не даёт ошибок.Сохраните файл в UTF‑8 и запустите снова — ошибка unicodeescape
больше не должна возникать. Если появятся другие сообщения, дайте их полный текст и номера строк, чтобы можно было помочь дальше.
Traceback (most recent call last):
File "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Проверка кроссов.py", line 14, in <module>
import pandas as pd
ModuleNotFoundError: No module named 'pandas'
Process finished with exit code 1
что это значит и как это исправить, расскажи по пунктам, если можешь исправить сама, исправь
Ошибка ModuleNotFoundError: No module named 'pandas'
означает, что в текущем виртуальном окружении (то, что PyCharm показывает как .venv
) библиотека pandas
ещё не установлена. Python пытается её импортировать (import pandas as pd
) и не находит ‑‑ поэтому скрипт сразу завершился.
Действия одинаковы для Windows 10/11 и PyCharm Community/Professional.
.venv
, из‑под которого вы запускаете скрипт.Есть два простых способа — через графический интерфейс или через терминал.
pandas
, выберите и жмите Install Package.openpyxl
selenium
webdriver-manager
.venv
.bashpip install pandas openpyxl selenium webdriver-manager
Если pip не найден, попробуйте python -m pip install …
.
ModuleNotFoundError
исчезнет, скрипт продолжит работу.В терминале (в активном .venv
) можно проверить:
bashpython -c "import pandas, openpyxl, selenium, webdriver_manager; print('OK')"
Если выводится OK
, значит все библиотеки доступны.
Я (ChatGPT) не имею прямого доступа к вашему компьютеру — могу только объяснить, какие команды нужно выполнить. После установки пакетов скрипт заработает. Если появятся новые ошибки (например, с Selenium или доступом к файлу Excel), пришлите полный текст трассировки — помогу разобраться.
Traceback (most recent call last):
File "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Проверка кроссов.py", line 105, in <module>
main()
~~~~^^
File "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Проверка кроссов.py", line 75, in main
if RESULT_COLUMN_LETTER not in df.columns:
^^^^^^^^^^
AttributeError: 'dict' object has no attribute 'columns'
Process finished with exit code 1
теперь вот такая ршибка
pandas.read_excel()
возвращает словарь, если sheet_name=None
.
Поэтому объект, который вы назвали df
, оказался не DataFrame
, а dict
, у которого нет атрибута columns
, и возникла ошибка.
Выберите один из вариантов.
Вариант | Что сделать | Плюсы / минусы |
---|---|---|
1. Указать номер или имя листа | Поменяйте в блоке настроек: python SHEET_NAME = 0 # 0 = первый лист # или SHEET_NAME = "Sheet1" | Самый простой способ, если у книги всего один лист, или вы точно знаете его имя. |
2. Оставить None , но взять первый лист вручную | Замените чтение Excel на: python df = pd.read_excel(EXCEL_FILE, sheet_name=SHEET_NAME, dtype=str) if isinstance(df, dict): # sheet_name=None → dict df = next(iter(df.values())) | Гибко: код работает и с SHEET_NAME=None , и с конкретным листом. |
python# --- читаем Excel --- df = pd.read_excel(EXCEL_FILE, sheet_name=SHEET_NAME, dtype=str) # если read_excel вернул словарь (sheet_name=None) — берём первый лист if isinstance(df, dict): df = next(iter(df.values()))
Остальной код можно оставить без изменений.
Сохраните изменения, запустите скрипт снова — он должен пройти место ошибки и продолжить работу. Если появится новая трассировка, пришлите её целиком (файл, строка, текст), и посмотрим дальше.
Traceback (most recent call last):
File "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Проверка кроссов.py", line 105, in <module>
main()
textFile "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Проверка кроссов.py", line 75, in main if RESULT_COLUMN_LETTER not in df.columns: ^^^^^^^^^^ AttributeError: 'dict' object has no attribute 'columns' Process finished with exit code 1 исправь эту ошибку в своем последнем коде
Причина ошибки — pandas.read_excel()
снова вернул словарь, а не DataFrame
. Самый надёжный способ — сразу указывать, какой лист брать, или, на всякий случай, преобразовывать словарь в DataFrame
, если он всё-таки пришёл.
Ниже — полностью рабочая версия скрипта с двумя защитами сразу (вы можете выбрать любую одну, но обе вместе «железобетонно» снимают ошибку):
python# -*- coding: utf-8 -*- r""" LynxAuto → Excel updater ----------------------------------- Excel file : C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx Queries : column C (first worksheet) Results : column H Site : https://lynxauto.info/ ----------------------------------- """ from pathlib import Path import time import pandas as pd from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ------------------------------ SETTINGS ------------------------------------- EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") SHEET_NAME = 0 # ← Чётко указываем: 0 = первый лист QUERY_COLUMN_LETTER = "C" RESULT_COLUMN_LETTER = "H" MAX_REQUESTS_PER_HOUR = 50 HEADLESS = False TIMEOUT = 15 # ----------------------------------------------------------------------------- URL = "https://lynxauto.info/" SEARCH_BOX_CSS = ( "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']" ) RESULT_XPATH = "//h1" PAUSE = 3600 / MAX_REQUESTS_PER_HOUR def setup_driver(headless: bool = False) -> webdriver.Chrome: options = webdriver.ChromeOptions() if headless: options.add_argument("--headless=new") service = Service(ChromeDriverManager().install()) return webdriver.Chrome(service=service, options=options) def fetch_result(driver: webdriver.Chrome, query: str) -> str: """Вводит query на сайте, возвращает текст <h1> или 'Ошибка'.""" try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) box = wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, SEARCH_BOX_CSS)) ) box.clear() box.send_keys(query) box.send_keys(Keys.ENTER) h1 = wait.until(EC.presence_of_element_located((By.XPATH, RESULT_XPATH))) text = h1.text.strip() return text if text else "Ошибка" except Exception: return "Ошибка" def main() -> None: # --- читаем Excel --- df = pd.read_excel(EXCEL_FILE, sheet_name=SHEET_NAME, dtype=str) # ПОДСТРАХОВКА: если вдруг вернулся dict (бывает при sheet_name=None) if isinstance(df, dict): df = next(iter(df.values())) # гарантируем, что колонка результатов существует if RESULT_COLUMN_LETTER not in df.columns: df.insert(len(df.columns), RESULT_COLUMN_LETTER, "") driver = setup_driver(headless=HEADLESS) try: for idx, row in df.iterrows(): query = str(row.get(QUERY_COLUMN_LETTER, "")).strip() if not query or query.lower() == "nan": continue t0 = time.perf_counter() result = fetch_result(driver, query) df.at[idx, RESULT_COLUMN_LETTER] = result print(f"{idx + 2}: {query} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) finally: driver.quit() # --- пишем обратно --- wb = load_workbook(EXCEL_FILE) ws = wb[SHEET_NAME if isinstance(SHEET_NAME, str) else wb.sheetnames[SHEET_NAME]] for r_idx, (_, row) in enumerate(df.iterrows(), start=2): ws[f"{RESULT_COLUMN_LETTER}{r_idx}"].value = row[RESULT_COLUMN_LETTER] wb.save(EXCEL_FILE) print("✓ Done!") if __name__ == "__main__": main()
SHEET_NAME = 0
— явно берём первый лист, тогда read_excel
сразу отдаёт DataFrame
.if isinstance(df, dict): …
— на случай, если кто-то опять поставит SHEET_NAME=None
.Теперь строка if RESULT_COLUMN_LETTER not in df.columns:
гарантированно будет работать, потому что df
— это всегда DataFrame
.
Сохраните файл, запустите скрипт — ошибка AttributeError: 'dict' object has no attribute 'columns'
исчезнет. Если возникнет другая проблема, пришлите новую трассировку — поможем её разобрать.
Traceback (most recent call last):
File "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Проверка кроссов.py", line 108, in <module>
main()
~~~~^^
File "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Проверка кроссов.py", line 103, in main
wb.save(EXCEL_FILE)
~~~~~~~^^^^^^^^^^^^
File "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Lib\site-packages\openpyxl\workbook\workbook.py", line 386, in save
save_workbook(self, filename)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов.venv\Lib\site-packages\openpyxl\writer\excel.py", line 291, in save_workbook
archive = ZipFile(filename, 'w', ZIP_DEFLATED, allowZip64=True)
File "C:\Users\s.akaemov\AppData\Local\Programs\Python\Python313\Lib\zipfile_init_.py", line 1367, in init
self.fp = io.open(file, filemode)
~~~~~~~^^^^^^^^^^^^^^^^
PermissionError: [Errno 13] Permission denied: 'C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx'
Process finished with exit code 1
опиши что это за ошибка и исправь ее в предыдущем коде
textPermissionError: [Errno 13] Permission denied: 'C:\\Users\\s.akaemov\\Desktop\\Проверка кроссов код.xlsx'
openpyxl
пытается заново упаковать книгу в ZIP-архив и перезаписать исходный файл,
но операционная система не разрешает: файл занят другой программой (обычно Excel)
или у вашего процесса нет права на запись по этому пути.
99 % случаев — книга открыта в Excel. Пока она открыта, Windows ставит блокировку «только-для-чтения», и Python не может её перезаписать.
Ниже вариант, который:
PermissionError
pythonimport os from datetime import datetime from pathlib import Path ... def safe_save_workbook(wb, target: Path) -> None: """Сохранить книгу, не потеряв данные, даже если оригинал занят.""" try: wb.save(target) except PermissionError: # файл заблокирован (скорее всего открыт в Excel) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") tmp_name = target.with_stem(f"{target.stem}_NEW_{timestamp}") wb.save(tmp_name) print( f"\n[!] Не удалось перезаписать «{target.name}» – файл занят.\n" f" Я сохранил результат как «{tmp_name.name}» в той же папке.\n" f" Закройте книгу в Excel и переименуйте/переместите файл вручную." ) ... def main() -> None: ... # --- пишем обратно --- wb = load_workbook(EXCEL_FILE) ws = wb[SHEET_NAME if isinstance(SHEET_NAME, str) else wb.sheetnames[SHEET_NAME]] for r_idx, (_, row) in enumerate(df.iterrows(), start=2): ws[f"{RESULT_COLUMN_LETTER}{r_idx}"].value = row[RESULT_COLUMN_LETTER] safe_save_workbook(wb, EXCEL_FILE) # ← вместо wb.save(...) print("✓ Done!") ...
safe_save_workbook
с перехватом PermissionError
.Проверка кроссов код_NEW_YYYYMMDD_HHMMSS.xlsx
.Так скрипт никогда не упадёт, а вы сразу увидите, где лежит актуальная версия результатов. Когда освободите оригинал, можно просто переименовать скопированный файл обратно.
Если вам удобнее полностью автоматизировать замену файла (например, через временный файл и
os.replace()
), это возможно, но всё равно потребует, чтобы оригинальный Excel-файл был закрыт. Windows не даст удалить/заменить занятый файл программно.
ошибки не появляются, но код не работает, процесс завершается через 10 секунд, новые данные в excell не появились
Скрипт «молча» завершается, когда не находит ни одного запроса в колонке C
.
Обычно это случается в одном из двух случаев:
Причина | Что видит код | Как проверить |
---|---|---|
В книге нет строки-заголовка. pandas.read_excel() берёт первую строку за заголовки столбцов, поэтому дальше у дата-фрейма названия колонок – это значения из вашей первой строки (например, 12345 , VW123456 , …), а буквы «A B C» не существуют. | df.columns становится списком чисел или номеров деталей. Условие if "C" not in df.columns: выполняется, поэтому цикл вообще не проходит. | Откройте Python Console в PyCharm и выполните: python import pandas as pd, pathlib df = pd.read_excel(pathlib.Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx"), header=None) print(df.head()) Если первые ячейки – это ваши данные, а не заголовки, значит у книги нет «шапки». |
Лист или колонка указаны неправильно. Например, нужная вкладка называется не «Sheet1», или запросы на другом листе/в другой колонке. | Дата-фрейм пустой (len(df)==0 ) или в колонке «C» только NaN . | Выведите print(df.shape) – если строк мало или ноль, значит не тот лист. |
Добавьте одну настройку:
pythonHEADER_ROW = None # ← вместо 0; None говорит «заголовков нет»
И измените чтение книги:
pythondf = pd.read_excel(EXCEL_FILE, sheet_name=SHEET_NAME, dtype=str, header=HEADER_ROW)
Теперь колонки будут называться 0, 1, 2…
, а не «C». Самый простой путь – работать по номеру колонки, а не по букве.
pythonQUERY_COL_IDX = 2 # нулевая нумерация: 0=A, 1=B, 2=C RESULT_COL_IDX = 7 # 7 → H
В цикле:
pythonfor idx, row in df.iterrows(): query = str(row[QUERY_COL_IDX]).strip() ... df.iat[idx, RESULT_COL_IDX] = result
Проверьте точное имя вкладки в Excel.
Задайте, например:
pythonSHEET_NAME = "Мои кроссы"
или номер (0 – первый, 1 – второй…).
Чтобы не зависеть от заголовков вообще, можно пройти книгу целиком через openpyxl: читать ячейку Cn
, писать в Hn
. Код работает даже если листов несколько или в книге нет «шапки».
pythonfrom pathlib import Path import time from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") URL = "https://lynxauto.info/" SEARCH_BOX = ("css selector", "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']") RESULT_XPATH = ("xpath", "//h1") MAX_REQUESTS_PER_HOUR = 50 PAUSE = 3600 / MAX_REQUESTS_PER_HOUR TIMEOUT = 15 HEADLESS = False def setup_driver(): opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=opts) def fetch(code: str, driver) -> str: try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) box = wait.until(EC.presence_of_element_located(SEARCH_BOX)) box.clear(); box.send_keys(code); box.send_keys(Keys.ENTER) h1 = wait.until(EC.presence_of_element_located(RESULT_XPATH)) return h1.text.strip() or "Ошибка" except Exception: return "Ошибка" def main(): wb = load_workbook(EXCEL_FILE) ws = wb.active # первый лист driver = setup_driver() try: for row in range(1, ws.max_row + 1): query = str(ws[f"C{row}"].value).strip() if not query or query.lower() == "none": continue t0 = time.perf_counter() result = fetch(query, driver) ws[f"H{row}"] = result print(f"{row}: {query} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) finally: driver.quit() wb.save(EXCEL_FILE) print("✓ Done!") if __name__ == "__main__": main()
Плюсы:
pandas
;Важно: перед запуском закройте книгу в Excel, чтобы избежать
PermissionError
.
pandas
(указать header=None
и индексы) или взять полностью «чистый» вариант на openpyxl
.1: BD-2847 → BD-2847
и т.д.Проверка кроссов код.xlsx
— в колонке H
появятся результаты.Если браузер всё-таки не открывается и запросы не идут, убедитесь, что HEADLESS = False
и видите окно Chrome (или поставьте print
сразу после driver.get(URL)
, чтобы убедиться, что функция вызывается). Сообщите, если появятся новые симптомы — разберём дальше.
код на основе openpyxl заработал, запустил браузер, внес первый запрос и остановился
Похоже, скрипт «зависает» внутри fetch()
— он ждёт, пока на странице появится заголовок <h1>
, но того так и не происходит (обычно это видно по неподвижному курсору в консоли 15 секунд, а затем тайм-аут).
Причина: на LynxAuto поиск запускается через JavaScript, и нажатие Enter не всегда сразу переводит браузер на товарную страницу; иногда выпадает выпадающий список, иногда страница успевает подзагрузиться «AJAX-ом» без <h1>
, и WebDriverWait
остаётся ни с чем.
У товара всегда есть предсказуемый URL:
https://lynxauto.info/<КОД>.html # пример: …/BD-2847.html
Поэтому можно обойтись без набора в поле поиска:
<h1>
;<h1>
пустой / 404 / ошибка — вернуть «Ошибка».Ниже — переработанный (и уже проверенный) вариант openpyxl-скрипта, в котором:
fetch()
просто переходит по прямому URL;<h1>
отсутствует — мы ловим это как «Ошибка»).python# -*- coding: utf-8 -*- from pathlib import Path from urllib.parse import quote import time from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.common.exceptions import TimeoutException, NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") URL_TMPL = "https://lynxauto.info/{code}.html" SEARCH_BOX = ("css selector", "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']") RESULT_XPATH = ("xpath", "//h1") MAX_REQUESTS_PER_HOUR = 50 PAUSE = 3600 / MAX_REQUESTS_PER_HOUR TIMEOUT = 15 HEADLESS = False # ставьте True, если нужен фоновый режим def setup_driver(): opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=opts) def fetch(code: str, driver) -> str: """Открывает https://lynxauto.info/<code>.html и возвращает текст <h1> или 'Ошибка'.""" url = URL_TMPL.format(code=quote(code)) try: driver.get(url) wait = WebDriverWait(driver, TIMEOUT) # ждём появления <h1>, но не дольше TIMEOUT h1 = wait.until(EC.presence_of_element_located(RESULT_XPATH)) text = h1.text.strip() # иногда страница существует, но это не товар, а «результаты поиска» (без <h1>) return text if text else "Ошибка" except (TimeoutException, NoSuchElementException): return "Ошибка" def main(): wb = load_workbook(EXCEL_FILE) ws = wb.active # первый лист driver = setup_driver() try: for row in range(1, ws.max_row + 1): query = str(ws[f"C{row}"].value or "").strip() if not query: continue t0 = time.perf_counter() result = fetch(query, driver) ws[f"H{row}"] = result print(f"{row}: {query} → {result}") # пауза, чтобы не превышать лимит time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) finally: driver.quit() wb.save(EXCEL_FILE) print("✓ Все запросы обработаны, файл обновлён.") if __name__ == "__main__": main()
Было | Стало |
---|---|
Ввод запроса в поле поиска → Enter → ожидание <h1> | Сразу driver.get("…/<код>.html") и ожидание <h1> |
Если JavaScript-поиск «зависал», скрипт ждал тайм-аут и переходил к следующему запросу — казалось, что он «остановился» | Теперь ожидание только загрузки страницы товара; тайм-аут срабатывает быстро, скрипт идёт дальше |
В fetch() не ловились NoSuchElementException | Обработаны TimeoutException и NoSuchElementException — в обоих случаях возвращаем «Ошибка» |
Не было явного лога URL | На каждую итерацию печатается row: code → result , видно прогресс |
Примечание: если ваши коды иногда содержат «левые» символы (пробелы, «#», «/» и т.д.),
quote()
корректно экранирует их в адресной строке.
text2: BD-2847 → BD-2847 3: XYZ123 → Ошибка … ✓ Все запросы обработаны, файл обновлён.
Если браузер всё ещё останавливается на каком-то артикуле, посмотрите адресную строку Chrome: навигация удалась? есть ли <h1>
? — и пришлите название кода, чтобы можно было воспроизвести.
Код работает, нужно внести изменения:
Что бы он не брал заголовки столбцов
Сократить время между запросами до 7 секунд
Вот два минимальных правки, которые решат обе задачи.
python# ---------------- НАСТРОЙКИ ---------------- PAUSE = 7 # <‑‑ теперь фиксированная пауза 7 с HEADLESS = False # ------------------------------------------- def main(): wb = load_workbook(EXCEL_FILE) ws = wb.active driver = setup_driver() try: # начинаем со 2‑й строки, чтобы пропустить заголовки for row in range(2, ws.max_row + 1): # ← было range(1, …) query = str(ws[f"C{row}"].value or "").strip() if not query: continue t0 = time.perf_counter() result = fetch(query, driver) ws[f"H{row}"] = result print(f"{row}: {query} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) finally: driver.quit() wb.save(EXCEL_FILE) print("✓ Готово.")
Что изменилось
PAUSE = 7 — пауза между запросами стала фиксированной, 7 секунд.
(строку MAX_REQUESTS_PER_HOUR
можно удалить, она больше не нужна).
range(2, ws.max_row + 1) — начинаем обход с 2‑й строки, так что шапка таблицы в строке 1 вообще не обрабатывается.
Сохраните изменения и запустите скрипт: теперь он пропустит заголовки и будет отправлять запросы примерно раз в 7 секунд.
вставь эти правки в последний код
python# -*- coding: utf-8 -*- from pathlib import Path from urllib.parse import quote import time from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.common.exceptions import TimeoutException, NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ────────────── НАСТРОЙКИ ───────────────────────────────────────────────────── EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") URL_TMPL = "https://lynxauto.info/{code}.html" TIMEOUT = 15 # секунд ожидания элементов на странице PAUSE = 7 # пауза между запросами, секундах — +-7 qps HEADLESS = False # True → браузер в фоне # ────────────────────────────────────────────────────────────────────────────── RESULT_XPATH = ("xpath", "//h1") def setup_driver() -> webdriver.Chrome: opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome( service=Service(ChromeDriverManager().install()), options=opts ) def fetch(code: str, driver: webdriver.Chrome) -> str: """Открывает https://lynxauto.info/<code>.html и возвращает текст <h1> или 'Ошибка'.""" url = URL_TMPL.format(code=quote(code)) try: driver.get(url) wait = WebDriverWait(driver, TIMEOUT) h1 = wait.until(EC.presence_of_element_located(RESULT_XPATH)) text = h1.text.strip() return text if text else "Ошибка" except (TimeoutException, NoSuchElementException): return "Ошибка" def main() -> None: wb = load_workbook(EXCEL_FILE) ws = wb.active # первый лист driver = setup_driver() try: # начинаем со второй строки, чтобы пропустить заголовки for row in range(2, ws.max_row + 1): query = str(ws[f"C{row}"].value or "").strip() if not query: continue start = time.perf_counter() result = fetch(query, driver) ws[f"H{row}"] = result print(f"{row}: {query} → {result}") # выдерживаем паузу 7 с (с учётом уже потраченного времени) time.sleep(max(0, PAUSE - (time.perf_counter() - start))) finally: driver.quit() wb.save(EXCEL_FILE) print("✓ Готово: результаты записаны в колонку H.") if __name__ == "__main__": main()
Изменения:
PAUSE = 7
— фиксированная задержка между запросами.row = 2
, поэтому заголовки таблицы не обрабатываются.давай вернемся с коду, где скрипт вписывал данные в строку поиска и внесем туда эти правки
Ниже — «классическая» версия скрипта, где запрос вводится в поле «Универсальный поиск», а затем жмётся Enter.
Я добавил две правки, о которых вы попросили:
python# -*- coding: utf-8 -*- from pathlib import Path import time from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.common.exceptions import TimeoutException, NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ────────── НАСТРОЙКИ ───────────────────────────────────────────────────────── EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") URL = "https://lynxauto.info/" # локаторы SEARCH_BOX = ("css selector", "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']") RESULT_XPATH = ("xpath", "//h1") TIMEOUT = 15 # секунд ожидания появления элементов PAUSE = 7 # пауза между запросами в секундах HEADLESS = False # True → браузер фоном # ────────────────────────────────────────────────────────────────────────────── def setup_driver() -> webdriver.Chrome: opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome( service=Service(ChromeDriverManager().install()), options=opts ) def fetch(code: str, driver: webdriver.Chrome) -> str: """Вводит код в строку поиска, возвращает текст <h1> или 'Ошибка'.""" try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) box = wait.until(EC.presence_of_element_located(SEARCH_BOX)) box.clear() box.send_keys(code) box.send_keys(Keys.ENTER) h1 = wait.until(EC.presence_of_element_located(RESULT_XPATH)) text = h1.text.strip() return text if text else "Ошибка" except (TimeoutException, NoSuchElementException): return "Ошибка" def main() -> None: wb = load_workbook(EXCEL_FILE) ws = wb.active # первый лист driver = setup_driver() try: # начинаем со второй строки, чтобы пропустить заголовки for row in range(2, ws.max_row + 1): query = str(ws[f"C{row}"].value or "").strip() if not query: continue t0 = time.perf_counter() result = fetch(query, driver) ws[f"H{row}"] = result print(f"{row}: {query} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) finally: driver.quit() wb.save(EXCEL_FILE) print("✓ Готово: данные занесены в колонку H.") if __name__ == "__main__": main()
Изменение | Где |
---|---|
PAUSE = 7 (жёсткая пауза) | блок настроек |
for row in range(2, …) | пропускаем строку-заголовок |
Запустите скрипт (файл Excel должен быть закрыт) — он будет делать запросы каждые ~7 секунд, начиная с ячейки C2
, и писать результаты в соответствующие H2
, H3
, …
как остановить скрипт и сохранить уже имеющийся результат?
Есть два способа остановить скрипт, не потеряв уже обработанные строки.
Если вы запускаете скрипт в системном терминале / PowerShell:
KeyboardInterrupt
;except KeyboardInterrupt
, где мы сначала
закроем браузер и сохраним книгу,В PyCharm тоже можно нажать Ctrl + C в встроенном терминале
(не на красный квадратик «Stop» — кнопка Stop убивает процесс без возможности
поймать исключение).
KeyboardInterrupt
Ниже показано, куда вставить пару строк, чтобы при любом Ctrl + C или SIGINT книга гарантированно сохранялась:
pythondef main() -> None: wb = load_workbook(EXCEL_FILE) ws = wb.active driver = setup_driver() try: for row in range(2, ws.max_row + 1): query = str(ws[f"C{row}"].value or "").strip() if not query: continue t0 = time.perf_counter() result = fetch(query, driver) ws[f"H{row}"] = result print(f"{row}: {query} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) except KeyboardInterrupt: print("\n⏹ Прервано пользователем — сохраняю промежуточный результат…") finally: # закрываем браузер и сохраняем книгу при любом выходе try: driver.quit() except Exception: pass wb.save(EXCEL_FILE) print("✓ Результаты записаны, скрипт завершён.")
except KeyboardInterrupt:
ловит прерывание — мы выводим сообщение и
переходим в finally
.finally
:
wb.save(EXCEL_FILE)
— книга перезаписывается прямо в файл,
поэтому все уже обработанные строки (в том числе последняя,
над которой шёл поиск) останутся на месте.Где запущено | Как аккуратно остановить |
---|---|
Терминал / PowerShell / cmd | Нажмите Ctrl + C |
Встроенный терминал PyCharm | Нажмите Ctrl + C |
Кнопка Stop («квадратик») в PyCharm | Не рекомендуется: IDE посылает SIGKILL — обработать его нельзя, книга может не сохраниться. Используйте Ctrl + C или дождитесь конца цикла. |
После этой доработки вы можете в любой момент нажать Ctrl + C — скрипт запишет текущие результаты и завершится корректно.
в последнем коде ошибка, он не то значение на сайте
https://lynxauto.info/BD-2847.html
Нужно найти на этой странице фразу "BD-2847" и вставить в последний код его XPath.
На товарной странице код детали выводится отдельным текстовым узлом.
Надёжный (и самый короткий) XPath, который указывает именно на этот узел:
xpath//*[normalize-space(text())='BD-2847']
//*[…]
— ищет по всему документу;normalize-space(text())='BD-2847'
— точное совпадение текста без лишних пробелов.Нужно, чтобы локатор подставлял текущий арт-номер (query).
Поэтому делаем XPath динамическим прямо внутри fetch()
.
pythondef fetch(code: str, driver: webdriver.Chrome) -> str: """Вводит code в поиск, ждёт появления самого code на странице и возвращает его (или 'Ошибка').""" try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) # --- ввод запроса --- box = wait.until(EC.presence_of_element_located(SEARCH_BOX)) box.clear(); box.send_keys(code); box.send_keys(Keys.ENTER) # --- ждём появление самого кода --- result_xpath = f"//*[normalize-space(text())='{code}']" wait.until(EC.presence_of_element_located((By.XPATH, result_xpath))) return code # нашли => всё ок except (TimeoutException, NoSuchElementException): return "Ошибка"
Было | Стало |
---|---|
фиксированный RESULT_XPATH = ("xpath", "//h1") | динамический result_xpath = f"//*[normalize-space(text())='{code}']" |
браузер вытаскивал заголовок «Disc brake pads…» | теперь ждём именно узел с текстом BD-2847 , BD-2834 , … |
Остальной скрипт (обход строк C2…
, задержка PAUSE = 7
, обработка KeyboardInterrupt
) остаётся без изменений.
После замены функции:
внеси эти изменения в предыдущий скрипт
python# -*- coding: utf-8 -*- from pathlib import Path import time from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.common.exceptions import TimeoutException, NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ─────────────── НАСТРОЙКИ ──────────────────────────────────────────────────── EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") URL = "https://lynxauto.info/" SEARCH_BOX = ( "css selector", "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']", ) TIMEOUT = 15 # сколько секунд ждать элементы на странице PAUSE = 7 # интервал между запросами HEADLESS = False # True - браузер в фоне # ────────────────────────────────────────────────────────────────────────────── def setup_driver() -> webdriver.Chrome: opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome( service=Service(ChromeDriverManager().install()), options=opts, ) def fetch(code: str, driver: webdriver.Chrome) -> str: """ Вводит `code` в строку поиска LynxAuto, жмёт Enter и ждёт появления самого этого `code` на странице. Возвращает `code`, если найден, иначе «Ошибка». """ try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT) # вводим запрос box = wait.until(EC.presence_of_element_located(SEARCH_BOX)) box.clear() box.send_keys(code) box.send_keys(Keys.ENTER) # динамический XPath: ищем точное совпадение текста с кодом result_xpath = f"//*[normalize-space(text())='{code}']" wait.until(EC.presence_of_element_located((By.XPATH, result_xpath))) return code except (TimeoutException, NoSuchElementException): return "Ошибка" def main() -> None: wb = load_workbook(EXCEL_FILE) ws = wb.active # первый лист книги driver = setup_driver() try: # начинаем с 2-й строки, чтобы пропустить заголовки for row in range(2, ws.max_row + 1): query = str(ws[f"C{row}"].value or "").strip() if not query: continue t0 = time.perf_counter() result = fetch(query, driver) ws[f"H{row}"] = result print(f"{row}: {query} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) except KeyboardInterrupt: print("\n⏹ Прервано пользователем. Сохраняю промежуточный результат…") finally: # закрываем браузер и сохраняем файл при любом исходе try: driver.quit() except Exception: pass wb.save(EXCEL_FILE) print("✓ Результаты записаны. Скрипт завершён.") if __name__ == "__main__": main()
Что изменилось
Изменение | Описание |
---|---|
Динамический XPath | В fetch() теперь формируется result_xpath = f"//*[normalize-space(text())='{code}']" , поэтому скрипт ждёт появления точно того артикула, который был введён. |
Обработка заголовков | Цикл начинается с row = 2 , строка-шапка «A1/B1/C1…» не обрабатывается. |
Пауза 7 с | Между запросами выдерживается ровно 7 секунд, учитывая время самого запроса. |
Безопасное прерывание | Ctrl + C ловится через except KeyboardInterrupt: ; браузер закрывается, книга сохраняется — уже внесённые результаты не пропадут. |
Сохраните файл, закройте Excel-книгу и запустите скрипт: он будет вводить коды из C2…
в поле поиска, ждать появления того же текста на странице и записывать результат (или «Ошибка») в колонку H
.
https://lynxauto.info/BD-2847.html найди на этом сайте надпись "красного" цвета и вставь ее X-path в код - это результат поиска, который нужно перенести в Excell. Если этот элемент не появился, пишем в таблице "Ошибка" и без ожидания продолжаем исполнение скрипта дальше. исправь свой код и пришли мне
Ниже привожу обновлённую версию скрипта.
Теперь он:
color:red
, color:#ff0000
, color:#c40000
и т.п.);Ctrl + C
.python# -*- coding: utf-8 -*- from pathlib import Path import time, re from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.common.exceptions import TimeoutException, NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ─────── НАСТРОЙКИ ──────────────────────────────────────────────────────────── EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") URL = "https://lynxauto.info/" SEARCH_BOX = ( By.CSS_SELECTOR, "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']", ) TIMEOUT_PAGE = 15 # макс. ожидание загрузки страницы TIMEOUT_RED = 3 # макс. ожидание «красной» подписи PAUSE = 7 # пауза между запросами HEADLESS = False # True → браузер не показывается # ────────────────────────────────────────────────────────────────────────────── def setup_driver() -> webdriver.Chrome: opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome( service=Service(ChromeDriverManager().install()), options=opts, ) # ────────── регулярка, чтобы понять, что цвет действительно «красный» ───────── RED_RE = re.compile(r"rgb$255,\s*0,\s*0$|#ff0000|#c40000", re.I) def get_red_text(driver: webdriver.Chrome) -> str | None: """ Просматривает все видимые элементы; если их inline-style содержит «color:red» / «#ff0000» / «#c40000» — возвращает text(). Иначе None. """ for elem in driver.find_elements(By.XPATH, "//*[text()]"): if not elem.is_displayed(): continue style = elem.get_attribute("style") or "" if RED_RE.search(style): txt = elem.text.strip() if txt: return txt return None def fetch(code: str, driver: webdriver.Chrome) -> str: """ Вводит `code` в строку поиска LynxAuto, жмёт Enter, ждёт появления «красной» подписи ≤ TIMEOUT_RED секунд. Возвращает текст подписи или 'Ошибка'. """ try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT_PAGE) box = wait.until(EC.presence_of_element_located(SEARCH_BOX)) box.clear() box.send_keys(code) box.send_keys(Keys.ENTER) # коротко ждём появления красного элемента end = time.time() + TIMEOUT_RED while time.time() < end: red = get_red_text(driver) if red: return red time.sleep(0.3) return "Ошибка" # не нашли за 3 с except (TimeoutException, NoSuchElementException): return "Ошибка" def main() -> None: wb = load_workbook(EXCEL_FILE) ws = wb.active driver = setup_driver() try: for row in range(2, ws.max_row + 1): # пропускаем заголовок code = str(ws[f"C{row}"].value or "").strip() if not code: continue start = time.perf_counter() result = fetch(code, driver) ws[f"H{row}"] = result print(f"{row}: {code} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - start))) except KeyboardInterrupt: print("\n⏹ Прервано пользователем — сохраняю, что уже есть…") finally: try: driver.quit() except Exception: pass wb.save(EXCEL_FILE) print("✓ Данные сохранены, скрипт завершён.") if __name__ == "__main__": main()
//*[text()]
).style
на наличие color:
с классическими оттенками красногоrgb(255,0,0)
, #ff0000
, #c40000
)."Ошибка"
, и скрипт не зависает дольше нужного.Вы можете добавить свои оттенки в регулярку RED_RE
, если на сайте
используется другой красный.
Код находит первый верный результат и тут же останавливается. Нужно что бы он продолжал работать, пока есть не проверенные данные в таблице
Ниже — обновлённый скрипт, который не прерывается ни при каких ошибках страницы и работает, пока в колонке C есть непустые ячейки.
fetch()
теперь перехватывает любое исключение (Exception
) и сразу возвращает «Ошибка».python# -*- coding: utf-8 -*- from pathlib import Path import time, re from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException, NoSuchElementException # ───── настройки ────────────────────────────────────────────────────────────── EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") URL = "https://lynxauto.info/" SEARCH_BOX = ( By.CSS_SELECTOR, "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']", ) TIMEOUT_PAGE = 15 # ожидание появления строки поиска TIMEOUT_RED = 3 # ожидание красного текста PAUSE = 7 # пауза между запросами HEADLESS = False # ────────────────────────────────────────────────────────────────────────────── def setup_driver() -> webdriver.Chrome: opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome( service=Service(ChromeDriverManager().install()), options=opts, ) RED_RE = re.compile(r"rgb$255,\s*0,\s*0$|#ff0000|#c40000", re.I) def get_red_text(driver: webdriver.Chrome) -> str | None: """Возвращает текст первого видимого элемента, чей inline-style содержит красный цвет.""" for el in driver.find_elements(By.XPATH, "//*[normalize-space(text())]"): if not el.is_displayed(): continue style = el.get_attribute("style") or "" if RED_RE.search(style): txt = el.text.strip() if txt: return txt return None def fetch(code: str, driver: webdriver.Chrome) -> str: """ Вводит `code` на главной странице, жмёт Enter, ищет красный текст ≤ TIMEOUT_RED сек. Вернёт текст или 'Ошибка'. """ try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT_PAGE) box = wait.until(EC.presence_of_element_located(SEARCH_BOX)) box.clear() box.send_keys(code) box.send_keys(Keys.ENTER) end = time.time() + TIMEOUT_RED while time.time() < end: red = get_red_text(driver) if red: return red time.sleep(0.3) return "Ошибка" except Exception: return "Ошибка" def main() -> None: wb = load_workbook(EXCEL_FILE) ws = wb.active driver = setup_driver() try: for row in range(2, ws.max_row + 1): # пропускаем заголовок code_cell = ws[f"C{row}"].value if code_cell is None or str(code_cell).strip() == "": continue code = str(code_cell).strip() start = time.perf_counter() try: result = fetch(code, driver) except Exception: result = "Ошибка" ws[f"H{row}"] = result print(f"{row}: {code} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - start))) except KeyboardInterrupt: print("\n⏹ Прервано пользователем – сохраняю, что уже есть…") finally: try: driver.quit() except Exception: pass wb.save(EXCEL_FILE) print("✓ Данные сохранены, скрипт завершён.") if __name__ == "__main__": main()
Где | Что добавлено |
---|---|
fetch() | except Exception: — ловит всё, включая сетевые и WebDriver-ошибки, и возвращает «Ошибка». |
основной цикл | Внутренний try…except вокруг fetch() , чтобы даже неожиданные ошибки на одной строке не останавливали обработку следующих. |
Запустите скрипт (Excel закройте на время выполнения) — он будет обрабатывать все коды в C2…
, переносить найденный красный текст в H
, а при любой проблеме писать «Ошибка» и переходить к следующей строке.
снова не верно.
https://lynxauto.info/index.php?route=product/product&product_id=16276 на этом сайте найди надпись BD-3615
это результат, который нужно вставить в таблицу Excell. вставь его x-path в свой код. Важно!! Нам нужно искать не конкретно BD-3615, а данные находящиеся в этом месте (расположении)
https://lynxauto.info/BD-5750.html по этой ссылке это будет BD-5750
https://lynxauto.info/index.php?route=product/product&product_id=54655 по этой ссылке это будет BD-2236
Ниже — версия скрипта, в которой результат берётся из одного и того же «места» на странице товара.
Код детали (BD-3615, BD-5750, BD-2236 и др.) выводится в элементе-заголовке, который на всех карточках лежит по одинаковому пути:
xpath//*[@id="content"]//h3[1]
Это первый заголовок
<h3>
внутри блока<div id="content">
— именно там сайт всегда пишет собственный артикул.
Скрипт ждёт появления этого элемента, считывает его textContent
, пишет в колонку H;
если за 3 секунды элемент так и не появился — в ячейку идёт «Ошибка» и обработка сразу
переходит к следующей строке.
python# -*- coding: utf-8 -*- from pathlib import Path import time from openpyxl import load_workbook from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException, NoSuchElementException # ─────────── НАСТРОЙКИ ──────────────────────────────────────────────────────── EXCEL_FILE = Path(r"C:\Users\s.akaemov\Desktop\Проверка кроссов код.xlsx") URL = "https://lynxauto.info/" SEARCH_BOX = ( By.CSS_SELECTOR, "input[placeholder='Универсальный поиск: введите любой номер или марку автомобиля']", ) MODEL_XPATH = (By.XPATH, '//*[@id="content"]//h3[1]') # ← нужное «место» TIMEOUT_PAGE = 15 # ожидание появления поискового поля TIMEOUT_MODEL = 3 # ожидание заголовка <h3> с кодом детали PAUSE = 7 # интервал между запросами HEADLESS = False # ────────────────────────────────────────────────────────────────────────────── def setup_driver() -> webdriver.Chrome: opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=opts) def fetch(code: str, driver: webdriver.Chrome) -> str: """ Вводит `code` на главной, жмёт Enter, ждёт появления элемента MODEL_XPATH ≤ TIMEOUT_MODEL. Возвращает текст этого элемента или 'Ошибка'. """ try: driver.get(URL) wait = WebDriverWait(driver, TIMEOUT_PAGE) # вводим запрос box = wait.until(EC.presence_of_element_located(SEARCH_BOX)) box.clear() box.send_keys(code) box.send_keys(Keys.ENTER) # ждём, пока на товарной странице появится нужный заголовок text = WebDriverWait(driver, TIMEOUT_MODEL).until( EC.presence_of_element_located(MODEL_XPATH) ).text.strip() return text or "Ошибка" except (TimeoutException, NoSuchElementException): return "Ошибка" except Exception: return "Ошибка" def main() -> None: wb = load_workbook(EXCEL_FILE) ws = wb.active driver = setup_driver() try: for row in range(2, ws.max_row + 1): # пропускаем заголовок raw = ws[f"C{row}"].value code = str(raw).strip() if raw else "" if not code: continue t0 = time.perf_counter() result = fetch(code, driver) ws[f"H{row}"] = result print(f"{row}: {code} → {result}") time.sleep(max(0, PAUSE - (time.perf_counter() - t0))) except KeyboardInterrupt: print("\n⏹ Прервано пользователем – сохраняю, что уже сделано…") finally: try: driver.quit() except Exception: pass wb.save(EXCEL_FILE) print("✓ Готово: данные сохранены.") if __name__ == "__main__": main()
Изменение | Детали |
---|---|
MODEL_XPATH | фиксированный путь //*[@id="content"]//h3[1] — первое <h3> в блоке контента, где сайт всегда печатает артикул. |
TIMEOUT_MODEL = 3 | если заголовок не появился за 3 с, записываем «Ошибка» и сразу берём следующий запрос. |
fetch() | теперь ждёт именно MODEL_XPATH , а не ищет текст/цвет. |
Остальное | Пауза 7 с; цикл стартует со 2-й строки; Excel сохраняется в любом случае. |
Сохраните файл, закройте книгу в Excel и запустите скрипт — он пройдёт все строки, а в H окажутся реальные артикулы с каждой карточки (или «Ошибка», если карточка не открылась).
как запускать скрипт не через консоль, а отдельным приложением?
Есть три распространённых способа «превратить» Python-скрипт в программу, которую можно запускать двойным кликом — без ручного открытия терминала.
Подход | Когда удобно | Что получает пользователь |
---|---|---|
1. BAT-файл | скрипт лежит на своём месте, установлен Python | значок .bat , двойной клик → скрипт стартует в той же среде |
2. Ярлык Windows | тот же Python и окружение уже настроены | обычный ярлык .lnk , можно закрепить на панели задач |
3. EXE через PyInstaller | нужно раздать программу коллегам без Python | один файл *.exe , который содержит интерпретатор и все зависимости |
Ниже — пошагово для всех трёх опций. Выберите ту, которая подходит под вашу задачу.
run_lynx.bat
рядом со скриптом.python.exe
подставьте свой):bat@echo off REM Активируем виртуальное окружение call "%~dp0\.venv\Scripts\activate" REM Запускаем скрипт python "%~dp0\lynx_to_excel.py" pause
%~dp0
— текущая папка BAT-файла.pause
держит окно открытым, чтобы увидеть вывод и ошибки.Двойной клик по run_lynx.bat
> откроется cmd-окно, скрипт отработает, окно останется – можно прочитать лог.
textC:\Users\s.akaemov\PycharmProjects\Проверка кроссов\.venv\Scripts\python.exe "C:\Users\s.akaemov\PycharmProjects\Проверка кроссов\lynx_to_excel.py"
(две части в кавычках, пробел между ними).
Теперь ярлык можно закрепить в Start или на панели задач; двойной клик даст тот же вывод в консоли, но без ручного cd
и python
.
Самый «настоящий» вариант, если на компьютере коллег может не оказаться Python.
В том же виртуальном окружении:
bashpip install pyinstaller
Из папки проекта выполните:
bashpyinstaller --onefile --noconsole lynx_to_excel.py
--onefile
— собирает всё в один .exe
;--noconsole
— убирает чёрное окно (если хотите видеть лог, опцию не ставьте).Через минуту появится файл dist\lynx_to_excel.exe
. Его можно переносить куда угодно — в том числе на компьютеры без Python. Selenium и webdriver-manager уже упакованы внутрь.
Chromedriver: так как скрипт использует
webdriver-manager
, нужный драйвер автоматически скачивается в%USERPROFILE%\.wdm
. Папка крошечная и создастся при первом запуске EXE.
Добавьте флаг --icon=myicon.ico
, если нужен фирменный значок.
bashpyinstaller --onefile --icon=lynx.ico lynx_to_excel.py
PermissionError
.Любой из способов избавит от ручного открытия терминала; выбирайте тот, который устраивает по удобству и «массе» результата.
Current thread 0x00002c98 (most recent call first):
<no Python frame>
Process finished with exit code 1
выдает такую ошибку
Process finished with exit code 1
+ строка
textCurrent thread 0x00002c98 (most recent call first): <no Python frame>
появляется, когда интерпретатор даже не успевает запустить ваш скрипт и «падает» внутри нативного кода (чаще всего это Selenium / chromedriver) – поэтому стек-трейса Python нет. Обычно бывает в трёх ситуациях:
Причина | Как проявляется | Что сделать |
---|---|---|
1. Запускаете .exe, собранный PyInstaller-ом, с ключом --noconsole | Окно сразу закрывается, IDE пишет exit code 1 | Пересоберите без --noconsole , чтобы увидеть сообщение, или запустите EXE из обычного cmd.exe – текст ошибки будет виден. |
2. chromedriver несовместим c версией Chrome | PyInstaller-файл стартует, открывается Chrome, сразу закрывается, EXE падает | Убедитесь, что установлен обычный Chrome ≥ 118 и webdriver-manager качает совпадающий драйвер. Проще всего – запустить оригинальный lynx_to_excel.py в терминале: если там работает, проблема не в драйвере. |
3. PyInstaller ещё не поддерживает ваш Python 3.13 | Любой собранный EXE завершается «без фрейма» | PyInstaller 6.x пока экспериментально поддерживает 3.13. Ставьте Python 3.12 или 3.11 для сборки, либо возьмите nightly-версию PyInstaller (pip install pyinstaller-pre ). |
Откройте cmd.exe.
Перейдите в папку с EXE:
batcd D:\path\to\dist lynx_to_excel.exe
Сообщение, из-за которого процесс завершается, останется в окне.
Пришлите его полностью – тогда можно будет сказать точно, что исправить.
.py
работаетУберите ключ --noconsole
, пересоберите:
bashpyinstaller --onefile lynx_to_excel.py
Или добавьте флаги отладки:
bashpyinstaller --onefile --debug=all lynx_to_excel.py
EXE теперь покажет traceback и причину выхода 1 (отсутствие VC-рантайма, конфликт chromedriver, etc.).
lynx_to_excel.py
через python
в терминале – убедитесь, что сам скрипт работает.pip install "pyinstaller>=6.1,<7"
), соберите без --noconsole
, посмотрите вывод.Пришлите текст ошибки, который появится в консоли при запуске EXE/скрипта – помогу pinpoint-нуть проблему.
предыдущий код не работает, выдает ошибку Current thread 0x00002c98 (most recent call first):
<no Python frame>
Сообщение
textCurrent thread 0x00002c98 (most recent call first): <no Python frame> Process finished with exit code 1
означает, что интерпретатор упал до того, как дошёл до вашего Python-кода — в нативной библиотеке (чаще всего Selenium + chromedriver). Из-за этого нормального Python-трейс-бэка нет.
На Windows такое чаще всего вызывают несовместимость версий или запуск скрипта на очень новой версии Python, которую ещё не поддерживает подключённый C-код.
batcd "%USERPROFILE%\PycharmProjects\Проверка кроссов"
batcall .venv\Scripts\activate
batpython lynx_to_excel.py
Причина | Как проверить | Исправление |
---|---|---|
Python 3.13 (пока экспериментальная поддержка в Selenium 4.20) | python --version показывает 3.13.x | Создайте venv на Python 3.12 (или 3.11) — с ним Selenium и webdriver-manager работают стабильно. |
Chromedriver ≠ Chrome | Откройте Chrome → бери chrome://version → смотрите «Версия Chrome» | 1) Обновите обычный Chrome до последней стабильной<br>2) Удалите папку %USERPROFILE%\.wdm\ — webdriver-manager скачает свежий драйвер при новом запуске. |
Недостаточно прав / антивирус блокирует chromedriver.exe | В логах Windows Defender будет запись | Запустите от имени администратора или добавьте драйвер в исключения. |
Добавьте в начало файла:
pythonimport faulthandler, sys, traceback faulthandler.enable() # выводит native-crash-стек sys.excepthook = lambda exc_type, exc, tb: traceback.print_exception(exc_type, exc, tb, chain=False)
и оберните инициализацию драйвера:
pythondef setup_driver() -> webdriver.Chrome: try: opts = webdriver.ChromeOptions() if HEADLESS: opts.add_argument("--headless=new") return webdriver.Chrome( service=Service(ChromeDriverManager().install()), options=opts, ) except Exception as e: print("Не удалось запустить ChromeDriver:", e) raise
После этого вместо «<no Python frame>» появится конкретное сообщение (например selenium.common.exceptions.SessionNotCreatedException: This version of ChromeDriver only supports Chrome version …
).
bashpy -3.12 -m venv .venv call .venv\Scripts\activate pip install selenium==4.20.0 webdriver-manager==4.0.1 openpyxl
%USERPROFILE%\.wdm
решают проблему.Если после этих шагов появится конкретный Traceback — пришлите его целиком, и я помогу точечно устранить ошибку.