ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Python] arsenic을 이용한 웹 크롤링
    Programming Language/Python 2018. 9. 6. 02:45

    브라우저 제어로 크롤링을 한다면 보통 Selenium을 사용합니다.

    하지만 Python Selenium은 Sync Syntax로 동작합니다.


    병렬로 크롤링을 하려면 프로세스를 여러 개 실행시키거나, 스레드를 생성해야 하는 번거로움이 있습니다.


    arsenic은 async/await syntax 를 지원하므로 기존 async function을 호출하는 방식과 동일하게 Async programming을 할 수 있습니다.

    속도에는 영향이 크게 없지만 AsyncIO Project에서 같은 syntax를 사용하여 Selenium과 동일한 방식으로 크롤링 가능하다는 이점이 있습니다.


    arsenic은 Python 3.6 이상부터 사용가능합니다.

    3.6 미만 버전에서 설치하고 실행하면 3.6 버전에서 추가된 문법으로 인해 Syntax Error가 발생합니다. (print formatting error..)


    먼저 ChromeDriver를 다운로드합니다.

    링크에서 지원 드라이버 버전을 확인할 수 있는데 2.37버전을 지원한다고 합니다.


    간단하게 웹사이트를 실행시켜 보겠습니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import asyncio
    from arsenic import get_session
    from arsenic.browsers import Chrome
    from arsenic.services import Chromedriver
     
     
    async def run():
        driver = Chromedriver(binary='/Users/baekchangmyeong/Downloads/chromedriver')
        browser = Chrome()
        
        async with get_session(driver, browser) as session:
            await session.get('https://www.naver.com/')
     
    cs


    코드처럼 ChromeDriver 생성자에 다운로드 받은 ChromeDriver 경로를 넣습니다. 
    이대로 실행하면 크롬 브라우저가 네이버를 실행시켜 줄 것입니다.

    주 메서드 레퍼런스

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    session.get_session(driver, browser) # 브라우저 세션을 가져옵니다.
    session.get(url) # url로 접속합니다.
    session.get_element(tagName[attribute]) # 엘리먼트를 이름, 속성 기반으로 검색합니다.
    session.get_elements(tagName[attribute]) # 엘리먼트들을 이름, 속성 기반으로 검색합니다.
    session.execute_script(script=jsCode) # 자바스크립트 코드를 실행합니다.
    element.get_element(tagName[attribute]) # 엘리먼트를 이름, 속성 기반으로 검색합니다.
    element.get_elements(tagName[attribute]) # 엘리먼트를 이름, 속성 기반으로 검색합니다.
    element.get_text() # 엘리먼트의 텍스트(innerHtml)를 가져옵니다.
    element.click() # 엘리먼트를 클릭합니다.
    element.get_attribute(attributeName) # 속성의 값을 속성 이름으로 가져옵니다.
    cs

    다 async function이므로 await를 사용하여 호출해야 합니다.
    더 자세한 기능들이 필요하다면 문서를 읽어보세요.

    한 가지 버그인지는 모르겠지만 클릭 후 뒤로가기를 하면 세션이 죽습니다.
    기존 세션 뿐 아니라 뒤로가기를 하기 전 세션까지 불러와지지 않습니다.

    저는 일단 HACK으로 그냥 페이지 이동 전 페이지로 세션을 다시 가져오는 방식으로 처리해 두었습니다.
    이유를 자세히 알기 위해서는 arsenic 코드를 분석해 봐야 할 것 같습니다.

    arsenic을 사용한 네이버 검색 테스트입니다.
    저는 arsenic을 사용할 경우가 많아서 중복 코드 제거를 위해 decorator 패턴으로 세션을 가져오도록 구현해 두었습니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    def browser():
        service = Chromedriver(binary='/Users/baekchangmyeong/chromedriver')
        browser = Chrome()
        def wrapper(func):
            @functools.wraps(func)
            async def wrapped():
                async with get_session(service, browser) as session:
                    copy_func = functools.partial(func, session=session)
                    return await copy_func()
            return wrapped
        return wrapper
     
    @browser()
    async def naver(session):
        await session.get('https://www.naver.com/')
        
        button = await session.get_element('button[id="search_btn"]')
        input = await session.get_element('input[id="query"]')
        
        await input.send_keys('검색 테스트')
        await button.click()
        html = await session.get_text()
        print(html)
    cs



    마지막으로 GUI가 불가능한 환경에서 실행해야 될 경우, Chrome 생성자에 옵션으로 --headless, --no-sandbox을 주면 됩니다.
    1
    2
    3
    browser = Chrome(chromeOptions={
        'args': ['--headless''--no-sandbox']
    })
    cs



    다만 이렇게 할 경우 서버에 추가적으로 설치 및 셋팅해야 하는 것이 있습니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # xvfb 설치 (디스플레이가 없는 환경에서 메모리 레벨에서 그래픽 연산을 처리하는 프로그램)
    apt-get install xvfb
     
    # npm 설치
    apt-get install npm
     
    # selenium-standalone 글로벌 설치
    npm install selenium-standalone -g
     
    # npm에서 사용할 브라우저 드라이버 설치 (arsenic이 2.37을 지원하므로 2.37 설치)
    selenium-standalone install --drivers.chrome.version=2.37
     
    # xvfb 실행
    xvfb-run --server-args="-screen 0, 1366x768x24" selenium-standalone start --drivers.chrome.version=2.37
    cs


Designed by Tistory.