Selenium
BeautifulSoup은 웹페이지가 로딩된 후 동적으로 불러들여지는 요소 (javascipt)에 대해서는 적절하게 대응을 할 수 없는 것 같다. 자바스크립트가 없는 페이지는 없으며, (내가 스크래이핑을 원하는 웹페이지 중에는) 결국 이에 대응할 수 있는 Selenium은 불가피했다. 뭔가 지금까지 코딩을 해오면서의 감으로 인한 것일까, Selenium의 속도부터 걱정됐다. 어쨌든 깔아서 코드에 적용해봤고, 역시나 느렸다. 너무 많이...
Selenium Browser
언제나 그렇듯 우리의 선배 개발자분들 께서 다져놓은 길이 있다. Selenium또한 성능향상을 꾀할 수 있다는 것. 일단 기본적으로 Selenium은 브라우저가 필요하다. Chrome, Firefox 등 코드가 실행되는 과정을 육안으로 확인할 수 있는 브라우저들 부터, Phantom JS, HTML... HINI? 뭐였는지 잘기억이 안난다. 어쨌든 포그라운드가 아닌 백그라운드에서 동작하는, 화면이 없는 브라우저들 까지 다양하게 사용할 수 있다. 내가 진행하는 프로젝트에서는 웹페이지의 자바스크립트 동작이 그렇게 많이 필요하지는 않지만, 그렇다고 필요없는 것도 아니어서 쓸 수 밖에 없었다. 어쨌든 Chrome을 사용했고, Selenium을 통해서 Chrome을 동작시키려면 별도의 Chromedriver 가 필요하다. (작업 디렉토리에 같이 두면 된다.)
Performance
이 포스팅에서는 Selenium 자체의 사용법이 아니라, 성능을 향상시킬 수 있는 방법을 다룰 것이다. 사용법이야 이 블로그보다 훌륭한 블로그들에서 많이 다뤘기에 (사실 성능향상도 없지는 않다) 다루지 않을 것이다. 여기서는 성능향상 방법을 찾아 Stackoverflow나 여러 블로그들을 돌아 다닌 결과를 종합에서 적을 것 이다.
근본적으로 생각해보면, Selenium에서 Webdriver (Chrome, Firefox driver와 같은..) 가 느린 이유는, 우리가 보는 브라우저상의 예쁘고 깔끔한 웹페이지를 그대로 구현해주기 때문이다. BeautifulSoup의 경우 단순히 html로 받아와 이를 파싱하지만, Selenium의 경우 html뿐만 아니라 css, javascript를 통해서 예쁘게 꾸미고 정렬해야 하기때문에 느린 것이다. + 드라이버 자체를 구동하는데 필요한 시간과 시스템 자원도 크다. 그렇다면 해결책은 하나다. 예쁘지 않게, 깔끔하지 않게 불러 오면 된다. 즉, 필요하지 않은 요소들은 로딩하지 않는다.
from selenium.webdriver.chrome.options import Options
selenium.webdriver.chrome.options에는 Chrome Webdrvier를 사용하면서 필요한 셋팅값을 설정할 수 있는 여러 메소드들이 존재한다. 그중에서도 add_argument와 experimental_options를 사용할 텐데 자세한 내용은 파일을 확인해보자.
class Options(object):
KEY = "goog:chromeOptions"
def __init__(self):
self._binary_location = ''
self._arguments = []
self._extension_files = []
self._extensions = []
self._experimental_options = {}
self._debugger_address = None
self._caps = DesiredCapabilities.CHROME.copy()
사용 예시는 이렇다.
options = Options()
prefs = {'profile.default_content_setting_values': {'cookies' : 2, 'images': 2,
'plugins' : 2, 'popups': 2, 'geolocation': 2,
'notifications' : 2, 'auto_select_certificate': 2,
'fullscreen' : 2,
'mouselock' : 2, 'mixed_script': 2,
'media_stream' : 2,
'media_stream_mic' : 2, 'media_stream_camera': 2,
'protocol_handlers' : 2,
'ppapi_broker' : 2, 'automatic_downloads': 2,
'midi_sysex' : 2,
'push_messaging' : 2, 'ssl_cert_decisions': 2,
'metro_switch_to_desktop' : 2,
'protected_media_identifier': 2, 'app_banner': 2,
'site_engagement' : 2,
'durable_storage' : 2}}
options.add_experimental_option('prefs', prefs)
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
# options.add_argument('--headless')
prefs에 필요한 설정값을 dict형태로 key : value로 설정하면 된다. key에 해당하는 value가 1이면 Enable, 2라면 Disable상태로 설정된다. 다음은 우리가 Chrome에서 설정할 수 있는 값에 대한 리스트이다.
cookies,
images,
javascript,
plugins,
popups,
geolocation,
notifications,
auto_select_certificate,
fullscreen,
mouselock,
mixed_script,
media_stream,
media_stream_mic,
media_stream_camera,
protocol_handlers,
ppapi_broker,
automatic_downloads,
midi_sysex,
push_messaging,
ssl_cert_decisions,
metro_switch_to_desktop,
protected_media_identifier,
app_banner,
site_engagement,
durable_storage
출처 : <https://stackoverflow.com/questions/49031428/how-to-disable-css-in-python-selenium-using-chromeoptions>
위에 실제로 적용한 코드 예시처럼 원하지 않는 기능을 Disable하면 된다. 실제로 위와같이 자바스크립트를 제외한 모든 설정을 꺼버리면 꽤 괜찮은 속도가 나온다. 자바스크립트도 꺼버리면 정말 빠르지만, 우리는 자바스크립트를 쓰려고 Selenium을 쓰는 것이니 이를 꺼버리면 사실상 Beautifulsoup와 다를게 없다..(실제로 자바스크립트가 동작하지 않은 결과를 가져온다)
StyleSheet(추가)
뭔가 이상한 점이 하나 있는데, 위의 설정 목록에서 CSS, Stylesheet와 같은 항목은 찾아볼 수 가 없다. Chrome에서는 CSS를 받지 않고서는 렌더링 자체를 할 수 없다고 하는데, 구글링을 해봐도 적절한 답이 나오지 않는다. 현재로서는 이렇게 마무리 짓고 추후에 방법을 생각해보자.
거기에 현재 Chrome Webdriver를 Headless 모드로 실행하면 앞서 설정했던 profile들이 적용되지 않는다. (image rendering disable...) chrome github에서 확인한 내용인데 현재로서는 Headless 모드에서 profile 설정은 지원하지 않는다고 한다. 생각보다 큰 작업이 될거라며.. (19년 2월 8일 기준)
'프로그래밍 > 크롤링(PYTHON)' 카테고리의 다른 글
Bot Detection / 크롤러 차단 / 크롤러 우회 #3 (1) | 2019.03.17 |
---|---|
Bot Detection / 크롤러 차단 / 크롤러 우회 #2 (9) | 2019.03.14 |
Bot Detection / 크롤러 차단 / 크롤러 우회 #1 (2) | 2019.03.11 |
[190119] requests In Python (0) | 2019.01.19 |
[190116] pytrend (0) | 2019.01.16 |