0%

selenium headless기능 적용하기

들어가기

저번에 Selenium과 chrom web driver를 사용해서 naver bike에서 바이크 브랜드 정보를 크롤링 하는 예제를 진행 했다.

뭔가 아쉬운 점은, 크롤링을 할 때마다, web driver에 의해서 크롬 브라우저가 열린다는 것이다.

아래처럼 크롤링 스크립트를 돌리면 크롬 브라우저가 열린다.

selenium%20headless%203032c18b510e4d13bfb9c27587403f67/Untitled.png

물론 디버깅 코드를 작성하는 동안 재대로 동작하는 지 확인 하기에 좋고, 크롤링 마지막 코드에

driver.quit() 명령으로 해당 web driver 브라우저를 종료 시킬 수 있다.

하지만 내가 원하는 것은 아예 web driver 브라우저가 열리지 않고 크롤링이 되는 것을 원한다.

만약 실제 데몬서비스등으로 돌릴 때, 위 처럼 web driver 브라우저가 열릴 필요가 없기 때문이다.

아직 해보지 않아서 정확히는 모르겠지만, 만약 리눅스 서버에서 스크립트를 돌릴 경우 desktop환경이 아닌경우 오류가 나라 수도 있을 것 같다.(내 추축이다. 아닐수도 있다.)

Selenium에서는 headless 라는 기능을 통해 크롤링 할때 web driver의 브라우저가 화면에 직접 열리지 않고, 뒤에 숨어서 동작하게 할 수 있다고 한다.

한번 해보자.

Selenium headless 적용하기

일단 기존의 Selenium 예제 코드를 준비하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from selenium import webdriver
import time

chromedriver = 'C:\dev_python\Webdriver\chromedriver.exe'
driver = webdriver.Chrome(chromedriver)

driver.get('https://auto.naver.com/bike/mainList.nhn')

print("+" * 100)
print(driver.title)
print(driver.current_url)
print("바이크 브랜드 크롤링")
print("-" * 100)

# 바이크 제조사 전체 페이지 버튼 클릭
bikeCompanyAllBtn = driver.find_element_by_css_selector("#container > div.spot_main > div.spot_aside > div.tit > a")
bikeCompanyAllBtn.click()

time.sleep(3)

# 바이크 제조사 1번 페이지 진입해서 바이크 리스트 추출
allBikeCompanyElement = driver.find_elements_by_css_selector(
"#_vendor_select_layer > div > div.maker_group div.emblem_area > ul > li")

# 바이크 첫 페이지 크롤링
for item in allBikeCompanyElement:
bikeComName = item.find_element_by_tag_name("span").text
if (bikeComName != ''):
print("바이크 회사명:" + bikeComName)
ahref = item.find_element_by_tag_name("a").get_attribute("href")
print('네이버 자동차 바이크제조사 홈 sub url:', ahref)
imgUrl = item.find_element_by_tag_name("img").get_attribute("src")
print('바이크 회사 엠블럼:', imgUrl)

time.sleep(3)

# 바이크 제조사 리스트의 다음 페이지 버튼을 찾아서 클릭하자.

nextBtn = driver.find_element_by_css_selector(
"#_vendor_select_layer > div > div.maker_group > div.rolling_btn > button.next")
# 다음 바이크 제조사 페이지 버튼이 활성화 여부
isExistNextPage = nextBtn.is_enabled()

if (isExistNextPage == True):
print("다음 페이지 존재함=======================================>")
nextBtn.click()
allBikeCompanyElement = driver.find_elements_by_css_selector(
"#_vendor_select_layer > div > div.maker_group div.emblem_area > ul > li")
for item in allBikeCompanyElement:
bikeComName = item.find_element_by_tag_name("span").text
if (bikeComName != ''):
print("바이크 회사명:" + bikeComName)
ahref = item.find_element_by_tag_name("a").get_attribute("href")
print('네이버 자동차 바이크제조사 홈 sub url:', ahref)
imgUrl = item.find_element_by_tag_name("img").get_attribute("src")
print('바이크 회사 엠블럼:', imgUrl)

# 크롤링이 끝나면 webdriver 브라우저를 종료한다.
driver.quit()

위 코드에 headless 기능을 적용해보자. 방법은 아주 간단하다.

headless를 기능을 사용하겠다고, web driver에게 알려주기만 하면 된다.

headless 기능을 활성화 하는 코드는 아래와 같다.

1
2
3
4
5
6
# webdirver옵션에서 headless기능을 사용하겠다 라는 내용
webdriver_options = webdriver.ChromeOptions()
webdriver_options .add_argument('headless')

chromedriver = 'C:/dev_python/Webdriver/chromedriver.exe'
driver = webdriver.Chrome(chromedriver, options=webdriver_options )

위 크롤링 코드에 적용 하면 아래처럼 된다.

headless가 적용된 예제코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from selenium import webdriver
import time

# webdirver옵션에서 headless기능을 사용하겠다 라는 내용
webdriver_options = webdriver.ChromeOptions()
webdriver_options .add_argument('headless')

chromedriver = 'C:\dev_python\Webdriver\chromedriver.exe'
driver = webdriver.Chrome(chromedriver, options=webdriver_options )

driver.get('https://auto.naver.com/bike/mainList.nhn')

print("+" * 100)
print(driver.title)
print(driver.current_url)
print("바이크 브랜드 크롤링")
print("-" * 100)

# 바이크 제조사 전체 페이지 버튼 클릭
bikeCompanyAllBtn = driver.find_element_by_css_selector("#container > div.spot_main > div.spot_aside > div.tit > a")
bikeCompanyAllBtn.click()

time.sleep(3)

# 바이크 제조사 1번 페이지 진입해서 바이크 리스트 추출
allBikeCompanyElement = driver.find_elements_by_css_selector(
"#_vendor_select_layer > div > div.maker_group div.emblem_area > ul > li")

# 바이크 첫 페이지 크롤링
for item in allBikeCompanyElement:
bikeComName = item.find_element_by_tag_name("span").text
if (bikeComName != ''):
print("바이크 회사명:" + bikeComName)
ahref = item.find_element_by_tag_name("a").get_attribute("href")
print('네이버 자동차 바이크제조사 홈 sub url:', ahref)
imgUrl = item.find_element_by_tag_name("img").get_attribute("src")
print('바이크 회사 엠블럼:', imgUrl)

time.sleep(3)

# 바이크 제조사 리스트의 다음 페이지 버튼을 찾아서 클릭하자.

nextBtn = driver.find_element_by_css_selector(
"#_vendor_select_layer > div > div.maker_group > div.rolling_btn > button.next")
# 다음 바이크 제조사 페이지 버튼이 활성화 여부
isExistNextPage = nextBtn.is_enabled()

if (isExistNextPage == True):
print("다음 페이지 존재함=======================================>")
nextBtn.click()
allBikeCompanyElement = driver.find_elements_by_css_selector(
"#_vendor_select_layer > div > div.maker_group div.emblem_area > ul > li")
for item in allBikeCompanyElement:
bikeComName = item.find_element_by_tag_name("span").text
if (bikeComName != ''):
print("바이크 회사명:" + bikeComName)
ahref = item.find_element_by_tag_name("a").get_attribute("href")
print('네이버 자동차 바이크제조사 홈 sub url:', ahref)
imgUrl = item.find_element_by_tag_name("img").get_attribute("src")
print('바이크 회사 엠블럼:', imgUrl)

아래처럼 실행 하면, 이번에는 webdirver 브라우저 없이 크롤링이 진행되는 것을 확인 할 수 있다.

selenium%20headless%203032c18b510e4d13bfb9c27587403f67/Untitled%201.png

기타 webdirver 옵션

1
2
3
4
5
6
7
8
9
10
# 브라우저의 사이즈 지정(화면 사이즈에 따라서 동적으로 엘리멘트가 변하는 경우 필요할듯)
webdriver_options .add_argument('windows-size=1920x1080')
# 그래픽 카드 사용하지 않음
webdriver_options .add_argument('disable-gpu')
# http request header의 User-Agent 변조, 기본으로 크롤링 할 경우
# 이 정보는 크롬 헤드리스 웹드라이버로 넘어가므로 똑똑한 웹서버는
# 이 정보를 보고 응답을 안해줄수도 있는데 이걸 피하기 위해 변조할수있다.
webdriver_options .add_arguemnt('User-Agent: xxxxxxxxxxxxxxx')
# 사용자 언어
webdriver_options .add_arguemnt('lang=ko_KR')

마무리

seleinum과 webdriver의 조합 말고도, Phantomjs라는 것을 사용해서도 크롤링을 할 수 있고 위 처럼 headless또한 적용이 가능하다고 한다.

하지만 요즘 크롬이 워낙 대세라서, 유지보수가 될지 안될지 잘 모를 Phantomjs를 굳이 사용할 필요는 없어 보인다.