[Python]AttributeError: 'Options' object has no attribute 'pop' 해결(부제: selenium과 seleniumwire의 webdriver option 설정이 얼마나 다를까?)
작성일: 2024-10-08
selenium-wire option 설정하기
이제 webdriver의 옵션을 설정하기 위해
ChromeOptions의 객체를 만들어준다. (변수 options에 해당)
from selenium.webdriver import ChromeOptions()
...
options = ChromeOptions()
options.add_argument('--start-maximized')
options.add_argument('--headless')
options.add_argument(f'user-agent={useragent}')
service = Service(executable_path=executable_path)
driver = webdriver.Chrome(service=service, seleniumwire_options=options)
...
+) add_argument 옵션에 들어갈 내용은 아래 오픈소스 docs나 공식문서를 참고한다.
c.f.
https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
chrome-launcher/docs/chrome-flags-for-tools.md at main · GoogleChrome/chrome-launcher
Launch Google Chrome with ease from node. Contribute to GoogleChrome/chrome-launcher development by creating an account on GitHub.
github.com
Chrome specific functionality
These are capabilities and features specific to Google Chrome browsers.
www.selenium.dev
이렇게 했더니
AttributeError: 'Options' object has no attribute 'pop'
이런 문제가 생김.
이유는 Options 객체를 seleniumwire options argument에 전달했기 때문이다.
‘options’ argument 자리는 파라미터에 dictionary형 변수만 받는데,
(그게 ChromeOptions()의 인스턴스인 것이고)
seleniumwire_options argument에는 list형 변수를 받는다고 한다.
(그래서 'pop' 같은 거 없다고 에러 난 것임.)
정리하자면,
변수 options를 ’options=’에 넣었어야 했는데
‘seleniumwire_options=’ 에 넣었던 것이 문제의 원인.
변명
그렇게 한 데에는 나름의 이유가 있었는데
기존 selenium webdriver였다면 다음과 같을 코드를 작성했을 것이다.
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver import Service
...
options = ChromeOptions()
service = Service(executable_path)
...
driver = webdriver.Chrome(service=service, options=options)
그런데 seleniumwire webdriver를 import하고 보니
seleniumwire_options가 활성화돼있고 options는 VSCode의 hover tooltip에 없길래
'아, seleniumwire webdriver는 option을 seleniumwire_options argument에 넣는구나.' 하고 생각했다.
그래서 아래처럼 적었다가 생긴 에러였다.
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver import Service
...
options = ChromeOptions()
service = Service(executable_path)
...
driver = webdriver.Chrome(service=service, seleniumwire_options=options)
해결
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver import Service
...
options = ChromeOptions()
service = Service(executable_path)
...
seleniumwire_options = {}
driver = webdriver.Chrome(service=service, options=options, seleniumwire_options=seleniumwire_options)
# driver = webdriver.Chrome(service=service, options=options)
이렇게 seleniumwire_options를 dictionary로 만들어서 해당 argument에 넣어주거나,
그냥 없이 options에만 값 넣어서 해결하면 된다.
돌아보며
1. 회고
내가 만든 게 아니기 때문에 직관적인 판단보다는
찾아보기 다소 귀찮더라도 쓰임새를 명확히 알고 쓰도록 하자.
(그게 시간이 덜 듦.)
2. 부제에 대한 답
options는 차이가 없다고 봐도 될 듯.
seleniumwire를 쓰려고 한 이유가
기존 selenium 유저로서, 러닝커브를 줄이려고 했기 때문인데,
잘 했다고 본다.