셀레니움에서 네트워크 로그 추출하기 위해서는 web driver의 LogType 중 performance 필드를 이용하면 된다.
사용 코드는 아래와 같다.
driver=webdriver.Chrome(options=chrome_options)
# 네트워크 로그 가져오기
network_logs = driver.get_log("performance")
위 코드로 수집된 log 파일에서 원하는 내용만 json 파일로 추출 후, 다운로드 받으면 업무 활용을 편하게 할 수 있다.
예를 들어, 특정 화면을 호출해서 스크롤을 하단 까지 내린 후,
- 호출된 이미지들 중 404 not found 발생하는 것이 있는지,
- 502 bad gateway 오류가 발생하는 이미지들은 있는지,
- 이를 직접 보고 있지 않아도, 다운로드 파일을 통해 확인할 수 있으며,
- 이러한 작업이 반복적이어서, 자동화하고 싶을 때 유용하다.
단발성이면, 직접 수작업으로 확인하는 것이 빠르겠지만, 루틴한 업무이면서 지속적인 작업이라면, 자동화할만하다.
▶ 네트워크 로그 추출 코드
#네트워크 로그 쓰기
def networklogwrite(filename):
# 네트워크 로그 가져오기
network_logs = driver.get_log("performance")
img_size = 0
with open(filename, "w", encoding="utf-8") as f:
f.write("[")
# 네트워크 로그에서 json 구조에서 원하는 부분만 추출하여 parsing 처리
for log in network_logs:
# json의 message key 부분 발췌
network_log = json.loads(log["message"])["message"]
# json의 method key 부분 발췌
if("Network.response" in network_log["method"]
or "Network.request" in network_log["method"]
or "Network.webSocket" in network_log["method"]):
#response 부분 발췌
if("response" in network_log["params"] ):
#.jpg, jpeg, 상태코드 404, 502 부분 있으면 파일에 write
if ("/jpg" in json.dumps(network_log)
or "/jpeg" in json.dumps(network_log)
or '"status": 404' in json.dumps(network_log)
or '"status": 502' in json.dumps(network_log)):
f.write(json.dumps(network_log, indent=2, ensure_ascii=False)+"\n\n")
f.write("]")
▶ 풀 코드
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
import json
# 시나리오
# 1. 지정한 URL 기준 하단까지 스크롤
# 2. 인피니티 스크롤인 경우 30,000 길이까지만 스크롤
# 3. 네트워크 응답로그중 jpg, jpeg, 404 not found, 502 bad gateway 발생인 경우, 파일 발췌하여 file 로 저장
mobile_emulation = { "deviceName": "iPhone 12 Pro" }
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--incognito") #시크릿모드
chrome_options.add_experimental_option("detach", True)
chrome_options.add_argument("--auto-open-devtools-for-tabs")
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
#network log 추출에 필요
chrome_options.add_argument("--enable-logging")
chrome_options.add_argument("--v=1")
#크롬 드라이버 있는 폴더를 지정한다.
chrome_options.add_argument("--user-data-dir=C:/크롬 드라이버 있는 폴더 지정")
chrome_options.set_capability('goog:loggingPrefs',{'performance': 'ALL'})
driver=webdriver.Chrome(options=chrome_options)
# 대상 URL 설정
url = 'https://shopping.naver.com/home'
driver.get(url)
# 인피니티 스크롤 대처 변수 설정
endScroll = 10000
#네이버 쇼핑 초기 레이어팝업 닫기 클릭하기
driver.find_element(By.XPATH,'//*[@id="gnb-header"]/div[4]/div/div/button[2]').send_keys(Keys.ENTER)
time.sleep(1)
#네트워크 로그 쓰기
def networklogwrite(filename):
# 네트워크 로그 가져오기
network_logs = driver.get_log("performance")
img_size = 0
with open(filename, "w", encoding="utf-8") as f:
f.write("[")
# 네트워크 로그에서 json 구조에서 원하는 부분만 추출하여 parsing 처리
for log in network_logs:
# json의 message key 부분 발췌
network_log = json.loads(log["message"])["message"]
# json의 method key 부분 발췌
if("Network.response" in network_log["method"]
or "Network.request" in network_log["method"]
or "Network.webSocket" in network_log["method"]):
#response 부분 발췌
if("response" in network_log["params"] ):
#.jpg, jpeg, 상태코드 404, 502 부분 있으면 파일에 write
if ("/jpg" in json.dumps(network_log)
or "/jpeg" in json.dumps(network_log)
or '"status": 404' in json.dumps(network_log)
or '"status": 502' in json.dumps(network_log)):
f.write(json.dumps(network_log, indent=2, ensure_ascii=False)+"\n\n")
f.write("]")
#스크롤 함수
def webScroll(i_present_location, i_filename):
print("#####Start Scroll#####")
time.sleep(1)
#스크롤 시작지점 초기화
from_scroll_height = 0
#스크롤 종료지점 초기화
to_scroll_height = 500
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
#scroll 진행
driver.execute_script("window.scrollTo("+ str(from_scroll_height) + "," + str(to_scroll_height) + ")")
time.sleep(1)
#현재 스크롤 위치
present_location = driver.execute_script("return window.pageYOffset")
#페이지 하단에 위치하면 종료
if last_height == present_location:
#하단 메뉴 보이고 나가기
driver.execute_script("window.scrollTo("+ str(to_scroll_height) + "," + str(from_scroll_height) + ")")
networklogwrite(i_filename)
break
#현 위치값이 인수로 넘어온 값보다 커지면 종료
elif present_location > i_present_location:
driver.execute_script("window.scrollTo("+ str(to_scroll_height) + "," + str(from_scroll_height) + ")")
networklogwrite(i_filename)
break
else:
#이동여부 판단 기준이 되는 이전 위치 값 수정
last_height = driver.execute_script("return window.pageYOffset")
#하단 위치 +500 씩 이동
from_scroll_height = to_scroll_height + 1
to_scroll_height = to_scroll_height + 500
print("#####End Scroll#####")
#스크롤 함수 호출 : 함수에 넘기는 인수는 무한스크롤에 대처하기 위해 현 스크롤 위치가 인수값을 넘기면 종료시키기 위해 전달
webScroll(endScroll, "logfile.json")
time.sleep(5)
driver.quit()
※ 실행 시 exception 발생되는 케이스
mac에서는 exception 발생되지 않는데, windows 10 환경에서 발생된다.
driver.get_log() 부분에서 “log type 'performance' not found” 오류가 발생하는 것인데,
이에 대한 해결은
크롬 옵션값에 “user-data-dir”를 지정하고 아래와 같이 bat 파일 만들어서 실행해 주면 된다.
chrome_options.add_argument("--user-data-dir=C:/크롬 드라이버 있는 폴더")
아래와 같이 bat 파일 생성해서 실행해 주면 된다.
#userdatabatch.bat
cmd > C:\Program Files (x86)\Google\Chrome\Application\chrome.exe --remote-debugging-port=9222 --user-data-dir="C:/크롬드라이버 있는 폴더”
※ log type "performance not found" 에러 발생 시 도움받은 블로그
'셀레니움(selenium)' 카테고리의 다른 글
셀레니움으로 화면 스크롤 내려보자 (with 파이썬) (0) | 2024.05.04 |
---|---|
셀레니움에서 클릭하는 법 (with python) (0) | 2024.05.02 |
셀레니움 find element 사용하기 (with python) (0) | 2024.04.29 |