셀레니움
셀레니움(Selenium)은 웹 드라이버 기반의 강력한 툴로써 크롤링 등 여러가지 용도로 널리 쓰이고 있는 라이브러리이다. 셀레니움의 강점은 그 쉬운 사용법에 있는데, 예를 들어 특정 url에 접근하여 페이지 스크린샷을 찍고싶다고 한다면 아래와 같이 간단한 코드로도 수행할 수 있다.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
# options.add_argument("--headless")
options.add_argument('log-level=3')
options.add_argument(f"--window-size=1920,1080")
options.add_argument("--hide-scrollbars")
driver = webdriver.Chrome(options=options, executable_path='E://chromedriver.exe')
driver.get('https://google.com')
driver.save_screenshot('E://screenshot_test.png')
이렇게 한줄로 스크린샷이 가능한가 하면, 해상도를 정해두었을 경우 headless로 백그라운드 실행을 하여도 그대로 스크린샷이 가능하다.
셀레니움 없이 PDF로 스크린샷 저장하기
그러나 크롤링을 하다보면 아무래도 웹드라이버를 기반으로 하는 셀레니움은 웹드라이버도 지속적으로 업데이트 해줘야하고 불편할때가 있다. 웹드라이버를 모종의 이유로 인해서 설치 및 사용하지 못하는 환경의 경우에는 더욱 난감하다. 셀레니움이 없이는 그렇다면 어떻게 크롤링 스샷을 찍을 수 있을까?
좀 불편하고 실제 웹드라이버보다 렌더링 품질이 떨어지긴 하지만 방법이 있다. imgkit, pdfkit와 같이 wkhtmltopdf 패키지를 이용하는 라이브러리들도 있는데, 에러가 많고 안되는 페이지도 많아서 찾다보니 정착한게 weasyprint다. 링크를 따라들어가서 필요 패키지들을 설치한 다음 python pip로 weasyprint를 설치해주면 사용 가능한데, 아래와 같이 beautifulsoup와 엮어서도 사용할 수 있다.
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
HTML(string=soup.prettify()).write_pdf('output.pdf'))
독립적으로도 url을 타고 들어가서 변환해주지만, 아무래도 크롤링을 하려면 beautifulsoup도 쓰게 되니까 예시코드에서는 그렇게 사용하였다.
그럼 얼마나 오래걸릴까? 안타깝게도 실험 결과 셀레니움으로 했을때는 총 14개 url 페이지에 대한 스크린샷을 찍는데에 총 32.18초(5회 반복 평균)가 걸렸고,
weasyprint 및 beautifulsoup을 이용했을 때는 같은 url list에 대해서 무려 438.36(!!)초로 매우매우 느리면서 한번쯤 에러도 나주는 모습을 확인할 수 있다.
다만, 결과물이 셀레니움의 경우 정말로 딱 창에서 보이는 부분에 국한되어있다면,
html을 pdf로 저장하는 경우 html로 구성되는 페이지를 전부 저장하기 때문에, 아래와 같이 여러장의 pdf로 저장할 수 있다.
상기 전체 테스트를 위해 사용한 코드 전문은 아래와 같다.
import os
from functools import wraps
def timer(n=1):
def decorator(func):
import time
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
print('Start with 1 iteration to warm up')
func(*args, **kwargs)
for _ in range(n):
func(*args, **kwargs)
end = time.time()
print(f'{func.__name__} - Average Time taken: {(end-start)/n} seconds')
return wrapper
return decorator
def use_selenium(url_list, output_dir):
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
options.add_argument('log-level=3')
options.add_argument(f"--window-size=1920,1080")
options.add_argument("--hide-scrollbars")
driver = webdriver.Chrome(options=options, executable_path='E://chromedriver.exe')
os.makedirs(os.path.join(output_dir,'selenium'), exist_ok=True)
@timer(n=5)
def crawl(url_list):
for url in url_list:
driver.get(url)
driver.save_screenshot(os.path.join(output_dir,'selenium',url.split('//')[1]+'.png'))
crawl(url_list)
def use_beautifulsoup(url_list, output_dir):
from weasyprint import HTML
from bs4 import BeautifulSoup
import requests
os.makedirs(os.path.join(output_dir,'beautifulsoup'), exist_ok=True)
@timer(n=5)
def crawl(url_list):
for url in url_list:
try:
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
HTML(string=soup.prettify()).write_pdf(os.path.join(output_dir,'beautifulsoup',url.split('//')[1]+'.pdf'))
except Exception as e:
print(f'{e}: {url}')
crawl(url_list)
import argparse
argparser = argparse.ArgumentParser()
argparser.add_argument('-s', '--selenium', help='Use selenium', action='store_true')
argparser.add_argument('-b', '--beautifulsoup', help='Use beautifulsoup', action='store_true')
if __name__ == '__main__':
args = argparser.parse_args()
url_list = ['https://google.com', 'https://yahoo.com', 'https://bing.com',
'https://duckduckgo.com', 'https://yandex.com', 'https://ask.com',
'https://aol.com', 'https://baidu.com', 'https://wikipedia.org',
'https://reddit.com', 'https://instagram.com', 'https://twitter.com','https://facebook.com','https://youtube.com']
output_dir = 'E://kclee/블로그/crawling/results'
if args.selenium:
use_selenium(url_list, output_dir)
if args.beautifulsoup:
use_beautifulsoup(url_list, output_dir)
if not args.selenium and not args.beautifulsoup:
print('Please select a method')
실행은 아래와 같이 하면 된다.
python <PYTHON_FILE_NAME>.py -b -s
이때, beautifulsoup만 테스트 해보고 싶으면 -b 옵션만, 셀레니움만 테스트 해보고 싶으면 -s 옵션만 넣어주면 된다.
'잡지식 저장고 > 크롤링' 카테고리의 다른 글
[KAIST한정]전문연구요원 출퇴근 관리 텔레그램 봇을 만들어보자(2) (47) | 2024.01.16 |
---|---|
[KAIST한정]전문연구요원 출퇴근 관리 텔레그램 봇을 만들어보자(1) (57) | 2024.01.16 |
Python Multiprocessing으로 병렬처리, 크롤링으로 맛보기 (3) | 2023.02.18 |
댓글