Dockerized Selenium Webscraper не ведет себя одинаково локально и на сервере ⇐ Linux
-
Anonymous
Dockerized Selenium Webscraper не ведет себя одинаково локально и на сервере
Я запускаю 3 докер-контейнера, все они расположены в папке rpdef.
Это архитектура моего проекта:
rpdef/db/db.sql (содержит скрипт базы данных)
rpdef/rpdef-api (содержит логику API)
rpdef/scrape-and-calculate (содержит файлы Python для моей сети Selenium скрапер)
rpdef/scrape-and-calculate/Dockerfile
rpdef/docker-compose.yml
Это мой файл rpdef/docker-compose.yml:
версия: '3' услуги: БД: изображение: MySQL: 8.0.17 среда: MYSQL_ROOT_PASSWORD: пройти MYSQL_DATABASE: rpdef порты: - "3308:3306" объемы: - ./db/db.sql:/docker-entrypoint-initdb.d/db.sql rpdef-api: сборка: ./rpdef-api порты: - «443:443» зависит от: - БД среда: MYSQL_HOST: БД MYSQL_USER: корень MYSQL_PASSWORD: пройти MYSQL_PORT: 3306 MYSQL_DB: rpdef поскрести и посчитать: сборка: ./очистить и вычислить порты: - «8000:8000» зависит от: - БД среда: MYSQL_HOST: БД MYSQL_USER: корень MYSQL_PASSWORD: пройти MYSQL_PORT: 3306 MYSQL_DB: rpdef Это мой файл rpdef/scrape-and-calculate/Dockerfile:
ИЗ Python:3.9.10 РАБОЧИЙ ДИАПАЗОН/приложение КОПИРУЙТЕ файл require.txt. КОПИРОВАТЬ. . ЗАПУСТИТЬ pip install -r требования.txt ЗАПУСК apt-get update && \ apt-get install -y wget распаковать && \ wget && \ apt install -y ./google-chrome-stable_current_amd64.deb && \ wget && \ разархивировать && \ mv chromedriver-linux64/chromedriver /usr/bin/chromedriver && \ rm -rf chrome-stable_current_amd64.deb CMD ["/bin/bash"] Когда я запускаю docker Compose Up и Python на своем локальном компьютере, все работает нормально, но когда я запускаю его на Linux-сервере, я получаю сообщение об ошибке:
Traceback (самый последний вызов — последний): Файл «/app/main.py», строка 8, в заголовок, groups_defense = Scrape.team_defenses(сезон) Файл «/app/scrape.py», строка 113, в Team_defenses. таблица = driver.find_element(By.CLASS_NAME, 'Crom_table__p1iZz') Файл «/usr/local/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py», строка 830, в find_element return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"] Файл "/usr/local/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py", строка 440, выполняется self.error_handler.check_response(ответ) Файл «/usr/local/lib/python3.9/site-packages/selenium/webdriver/remote/errorhandler.py», строка 245, в check_response поднять класс исключения_класса (сообщение, экран, трассировка стека) selenium.common.Exceptions.NoSuchElementException: Сообщение: такого элемента нет: невозможно найти элемент: {"method": "css selector", "selector":".Crom_table__p1iZz"} (Информация о сеансе: chrome-headless-shell=122.0.6261.94) Трассировки стека: 0 0x55ce9b9fcd93 1 0x55ce9b6e0337 2 0x55ce9b72bd60 3 0x55ce9b72be51 4 0x55ce9b76fbc4 5 0x55ce9b74e46d 6 0x 55ce9b76d12d 7 0x55ce9b74e1e3 8 0x55ce9b71e135 9 0x55ce9b71f13e 10 0x55ce9b9c0e4b 11 0x55ce9b9c4dfa 12 0x55ce9b9ad6d5 13 0x55ce9b9c5a6f 14 0x55ce9b99169f 15 0x55ce9b9ea098 16 0x55ce9b9ea262 17 0x55ce9b9fbf34 18 0x7fdb7d7d8ea7 start_thread Эта ошибка возникает, потому что webscrapper открывает веб-сайт, на котором нет элемента с селектором: «Crom_table__p1iZz». Эта ошибка появлялась раньше, когда я пытался запустить локально, но я исправил ее, установив правильные версии google-chrome и Chromedriver и используя собственный пользовательский агент. Версии google-chrome и Chromedriver одинаковы для локального и серверного Docker.
Насколько я понимаю, это должно работать одинаково, если докер-контейнеры работают на моем локальном компьютере или на сервере Linux, но они работают и ведут себя по-разному. Почему это так и как это исправить?
Вот моя конфигурация драйвера и метод очистки веб-страниц:
def team_defenses(сезон): url = 'https://www.nba.com/stats/teams/defense?Season=' + сезон драйвер = get_web_driver() driver.get(url) # Подождите, пока таблица загрузится, если она не загружает отображаемый контент пытаться: WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'Crom_table__p1iZz'))) кроме: с open('error_page_source.txt', 'w') как f: f.write(driver.page_source) # Находим элемент таблицы таблица = driver.find_element(By.CLASS_NAME, 'Crom_table__p1iZz') #Находим все строки в таблице rows = table.find_elements(By.TAG_NAME, 'tr') team_defenses = [] # Проходим по каждой строке и извлекаем данные из каждой ячейки для строки в строках: я = 0 #Находим все ячейки в строке ячейки = row.find_elements(By.TAG_NAME, 'td') команда='' защита_rtg = 0 opp_pts_paint = 0 для ячейки в ячейках: если я == 1: команда = ячейка.текст Элиф я==6: def_rtg = float(cell.text) Элиф я==14: opp_pts_paint = float(cell.text) я+=1 если команда: team_defenses.append([get_team_abbrivation(team), def_rtg, opp_pts_paint]) заголовок = ['Команда', 'DEF', 'RDEF'] вернуть заголовок, team_defenses защита get_web_driver(): заголовок = Заголовки( браузер="chrome", # Генерировать только Chrome UA os="win", # Генерировать только платформу Windows headers=False # генерировать разные заголовки ) chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--headless') # Запуск Chrome в безголовом режиме chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-dev-shm-usage') chrome_options.add_argument('--disable-gpu') customUserAgent = header.generate()['User-Agent'] chrome_options.add_argument(f"user-agent={customUserAgent}") драйвер = вебдрайвер.Chrome( options=chrome_options ) возвратный водитель Любая помощь очень ценится.
Я запускаю 3 докер-контейнера, все они расположены в папке rpdef.
Это архитектура моего проекта:
rpdef/db/db.sql (содержит скрипт базы данных)
rpdef/rpdef-api (содержит логику API)
rpdef/scrape-and-calculate (содержит файлы Python для моей сети Selenium скрапер)
rpdef/scrape-and-calculate/Dockerfile
rpdef/docker-compose.yml
Это мой файл rpdef/docker-compose.yml:
версия: '3' услуги: БД: изображение: MySQL: 8.0.17 среда: MYSQL_ROOT_PASSWORD: пройти MYSQL_DATABASE: rpdef порты: - "3308:3306" объемы: - ./db/db.sql:/docker-entrypoint-initdb.d/db.sql rpdef-api: сборка: ./rpdef-api порты: - «443:443» зависит от: - БД среда: MYSQL_HOST: БД MYSQL_USER: корень MYSQL_PASSWORD: пройти MYSQL_PORT: 3306 MYSQL_DB: rpdef поскрести и посчитать: сборка: ./очистить и вычислить порты: - «8000:8000» зависит от: - БД среда: MYSQL_HOST: БД MYSQL_USER: корень MYSQL_PASSWORD: пройти MYSQL_PORT: 3306 MYSQL_DB: rpdef Это мой файл rpdef/scrape-and-calculate/Dockerfile:
ИЗ Python:3.9.10 РАБОЧИЙ ДИАПАЗОН/приложение КОПИРУЙТЕ файл require.txt. КОПИРОВАТЬ. . ЗАПУСТИТЬ pip install -r требования.txt ЗАПУСК apt-get update && \ apt-get install -y wget распаковать && \ wget && \ apt install -y ./google-chrome-stable_current_amd64.deb && \ wget && \ разархивировать && \ mv chromedriver-linux64/chromedriver /usr/bin/chromedriver && \ rm -rf chrome-stable_current_amd64.deb CMD ["/bin/bash"] Когда я запускаю docker Compose Up и Python на своем локальном компьютере, все работает нормально, но когда я запускаю его на Linux-сервере, я получаю сообщение об ошибке:
Traceback (самый последний вызов — последний): Файл «/app/main.py», строка 8, в заголовок, groups_defense = Scrape.team_defenses(сезон) Файл «/app/scrape.py», строка 113, в Team_defenses. таблица = driver.find_element(By.CLASS_NAME, 'Crom_table__p1iZz') Файл «/usr/local/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py», строка 830, в find_element return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"] Файл "/usr/local/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py", строка 440, выполняется self.error_handler.check_response(ответ) Файл «/usr/local/lib/python3.9/site-packages/selenium/webdriver/remote/errorhandler.py», строка 245, в check_response поднять класс исключения_класса (сообщение, экран, трассировка стека) selenium.common.Exceptions.NoSuchElementException: Сообщение: такого элемента нет: невозможно найти элемент: {"method": "css selector", "selector":".Crom_table__p1iZz"} (Информация о сеансе: chrome-headless-shell=122.0.6261.94) Трассировки стека: 0 0x55ce9b9fcd93 1 0x55ce9b6e0337 2 0x55ce9b72bd60 3 0x55ce9b72be51 4 0x55ce9b76fbc4 5 0x55ce9b74e46d 6 0x 55ce9b76d12d 7 0x55ce9b74e1e3 8 0x55ce9b71e135 9 0x55ce9b71f13e 10 0x55ce9b9c0e4b 11 0x55ce9b9c4dfa 12 0x55ce9b9ad6d5 13 0x55ce9b9c5a6f 14 0x55ce9b99169f 15 0x55ce9b9ea098 16 0x55ce9b9ea262 17 0x55ce9b9fbf34 18 0x7fdb7d7d8ea7 start_thread Эта ошибка возникает, потому что webscrapper открывает веб-сайт, на котором нет элемента с селектором: «Crom_table__p1iZz». Эта ошибка появлялась раньше, когда я пытался запустить локально, но я исправил ее, установив правильные версии google-chrome и Chromedriver и используя собственный пользовательский агент. Версии google-chrome и Chromedriver одинаковы для локального и серверного Docker.
Насколько я понимаю, это должно работать одинаково, если докер-контейнеры работают на моем локальном компьютере или на сервере Linux, но они работают и ведут себя по-разному. Почему это так и как это исправить?
Вот моя конфигурация драйвера и метод очистки веб-страниц:
def team_defenses(сезон): url = 'https://www.nba.com/stats/teams/defense?Season=' + сезон драйвер = get_web_driver() driver.get(url) # Подождите, пока таблица загрузится, если она не загружает отображаемый контент пытаться: WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'Crom_table__p1iZz'))) кроме: с open('error_page_source.txt', 'w') как f: f.write(driver.page_source) # Находим элемент таблицы таблица = driver.find_element(By.CLASS_NAME, 'Crom_table__p1iZz') #Находим все строки в таблице rows = table.find_elements(By.TAG_NAME, 'tr') team_defenses = [] # Проходим по каждой строке и извлекаем данные из каждой ячейки для строки в строках: я = 0 #Находим все ячейки в строке ячейки = row.find_elements(By.TAG_NAME, 'td') команда='' защита_rtg = 0 opp_pts_paint = 0 для ячейки в ячейках: если я == 1: команда = ячейка.текст Элиф я==6: def_rtg = float(cell.text) Элиф я==14: opp_pts_paint = float(cell.text) я+=1 если команда: team_defenses.append([get_team_abbrivation(team), def_rtg, opp_pts_paint]) заголовок = ['Команда', 'DEF', 'RDEF'] вернуть заголовок, team_defenses защита get_web_driver(): заголовок = Заголовки( браузер="chrome", # Генерировать только Chrome UA os="win", # Генерировать только платформу Windows headers=False # генерировать разные заголовки ) chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--headless') # Запуск Chrome в безголовом режиме chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-dev-shm-usage') chrome_options.add_argument('--disable-gpu') customUserAgent = header.generate()['User-Agent'] chrome_options.add_argument(f"user-agent={customUserAgent}") драйвер = вебдрайвер.Chrome( options=chrome_options ) возвратный водитель Любая помощь очень ценится.
Мобильная версия