ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [파이썬] Beautifulsoup 를 이용한 웹페이지 스크래핑
    #파이썬 2020. 3. 25. 19:54

    수정일 : 2020-11-23

    각종 웹에 일반적으로 크롤러라고 소개되어있으나 PyPi의 Beautifulsoup 프로젝트를 보면 분명 "
    Beautiful Soup is a library that makes it easy to scrape information from web pages." 로 소개되어 있습니다. 물론 bs 도구를 활용해서 크롤러를 만들어볼 순 있을 것 같습니다. 하지만 이 글에서는 크롤링과 관련된 내용은 없으며 스크래핑하는 것에 대해서만 다룹니다.

    더불어 크롤링(Crawling)는 일반적으로 검색엔진에서 사용되는 웹에 있는 문서들을 추적하는 기술입니다. URL이 주어지면 이 URL에 포함된 혹은 관련된 하이퍼링크들을 재귀적으로 탐색해서 많은 웹문서들을 (효율적으로) 탐색하고 필요한 데이터들을 분석하는 게 크롤러의 주 목적인 것 같습니다. 물론 관련 논문들을 많이 읽어보지 않아 정확하진 않겠지만 이런 내용들이 있다는 것에 대해 인지하시고 해당 문서를 읽어주시면 감사하겠습니다! 

    BeautifulSoup는 웹페이지 스크래퍼중 가장 보편적으로 사용되는 파이썬 모듈이다. 설치방법을 간단하게 소개하고, 개인적으로 자주 사용하는 함수들을 정리해본다.

    # Python2
    pip install beautifulsoup4
    
    # Python3
    pip3 install beautifulsoup4
    
    # Optional
    pip install lxml
    pip3 install lxml

    설치는 간단하게 pip를 이용해서 설치하면 되며, lxml 모듈은 선택사항이다. bs4 모듈에 html parser는 내장되어있지만, lxml 의 속도가 더 빠르다고 하니, 참고해서 사용하면 되겠다. 사용법은 같다.

    import requests
    from bs4 import BeautifulSoup
    
    res = requests.get('URL')
    html = res.text
    '''
    f = open('test.html','r')
    html = f.read()
    '''
    soup = BeautifulSoup(html,'lxml') # BeautifulSoup(html,'html.parser')
    

    여기까지가 기본적인 형태로, html 코드를 웹으로 받든, 파일 입출력으로 열든해서 BeautifulSoup에 넣어주면, 준비가 끝난다. 

    # input 태그 가져오기
    # html 에서 제일 처음 나오는 태그만 가져옴
    result = soup.find('input')
    
    # name 속성이 id 인 input 태그 가져오기
    result = soup.find('input',{'name':'id'})
    
    # type 속성이 hidden 인 input 태그의 value 속성 가져오기
    result = soup.find('input',{'name':'hidden'}).get('value')
    
    # p 태그 사이 내용 가지오기
    # ex) <p> Hello World! </p> -> result = "Hello World!"
    result = soup.find('p').text
    
    # html 내의 모든 태그 다 가져오기
    # 해당 태그가 리스트 형태로 반환됨
    result = soup.find_all('input')
    
    ex) 모든 form 태그 가져오기
    for f in soup.find_all('form'):
    	# 해당 form 태그 하위의 name 속성이 test 인 input 태그 가져오기
    	inp_tag = f.find('input',{'name':'test'})
    
    # 가져온 태그에 옵션 존재 여부 확인하기
    for form in soup.find_all('form'):
    	# has_attr 함수로 옵션 유무 확인
    	if form.has_attr('action'):
        		print('This form has action option!')
        		# 옵션 값 가져오기
            	print('action : "+form.get('action')
    

    매번 간단하게만 사용하는지라 find함수와 find_all, has_attr 함수 정도만 알면, 어지간한 스크래핑은 됐던 것 같다. 추후 자주 사용하게 되는 함수가 있으면, 업데이트할 예정이다.

    ※ 윤리적인 크롤링 및 스크래핑(robots.txt)

    크롤링이든 스크래핑이든 합법과 불법의 경계가 모호할 수 있으며 실제로 처벌된 사례도 있기 때문에 주의해야한다. 우선 이런 봇들을 활용할 때 사이트별 robots.txt를 확인한다.

    robots.txt 는 사이트의 최상위 경로에 존재(예: http://www.naver.com/robots.txt)에 존재한다. (없는 곳 도있음) 해당 문서를 확인해보면 봇의 문서 수집 허용 여부에 대한 규칙을 해두었고 요청할 때 delay 시간 같은 것 역시 표기되어 있다. 

    User-Agent: googlebot
    Disallow: /

    위와 같은 규칙이 있다면 googlebot 에 대해서 모든 페이지에 대한 봇의 데이터 수집을 허용하지 않는다는 의미이다. 

    User-Agent: *
    Disallow: /mail
    Crawl-delay: 15

    위와 같은 경우 모든 봇들에 대해서 /mail 하위에 있는 문서들은 수집을 허용하지 않으며 이외의 경우는 15초마다 요청을 하라는 규칙이다. (서버에 대한 부하를 줄이기 위함) 

    robots.txt에 관한 규칙은 developers.google.com/search/reference/robots_txt?hl=ko 을 참고하면 좋을 것 같다. 뿐만 아니라 페이지의 <meta> 태그로 크롤링에 대한 규칙(noindex, nofollow 등)을 명시할 수 있으며 HTTP 응답 헤더에 X-Bots-Tag를 용해서 규칙을 지정할 수 있다. 이와 관련된 내용은 developers.google.com/search/reference/robots_meta_tag?hl=ko 해당 링크를 확인하면 잘 정리되어있다.

    이런 규칙들은 강제로 차단하는 효과는 없기 때문에 코드를 작성하는쪽에서 해당 규칙을 확인하고 따로 처리를 해줘야 하며 만약 규칙을 지키지 않았을 경우 향후 문제가 발생할 소지가 있기 때문에 반드시 지켜서 프로그램을 작성해야 한다. 그리고 이렇게 수집된 내용들은 개인적으로 이용하는 것 정도는 가능한 것 같지만 재 게시하거나 상업적으로 이용하는 등 재사용할 경우 저작권법 등으로 문제 될 수 있기 때문에 반드시 수집된 데이터에 대한 법적 범위를 확인할 필요가 있다. 

     

    댓글 0

Designed by Tistory.