본문 바로가기
IT/Python

파이썬 크롤링-01. 크롤링의 기초

by 무녈 2021. 6. 21.

자료의 출처는 엘리스 AI 트랙(https://aitrack.elice.io/) '파이썬 크롤링'  이며, 학습 후 정리한 내용입니다.

⚡️올바르지 않은 내용이 있을 경우 댓글로 남겨주시면 감사하겠습니다.⚡️


수강목표

  • 파이썬 프로그래밍을 연습할 수 있다.
  • 크롤링으로 웹 페이지의 데이터를 자유롭게 얻을 수 있다.
  • 크롤링 기능을 가진 나만의 프로그램을 작성할 수 있다.

크롤링의 기초

크롤링

크롤링이란?

웹 페이지에서 필요한 데이터를 추출해내는 작업

크롤링을 하는 프로그램: 크롤러

 

웹 페이지는 정보를 HTML 문서로 표현

크롤링을 위해 필요한 것

웹 페이지HTML을 얻기 위해 request 라이브러리를,

가져온 HTML을 분석하기 위해 BeautifulSoup 라이브러리를 사용한다.

BeautifulSoup

BeautifulSoup 라이브러리

HTML, XML, JSON 등 파일의 구문을 분석하는 모듈

웹 페이지를 표현하는 HTML을 분석하기 위해 사용

from bs4 import BeautifulSoup

soup = BeautifulSoup(open("index.html"), "html.parser")

HTML 파일로 BeautifulSoup 객체를 만들 수 있다.

변수 이름은 관습적으로 soup라고 짓는다.

 

"html.parser"의 의미는, BeautifulSoup 객체에게 "HTML을 분석해라"라고 알려주는 의미

soup.find("p")		# 처음 등장하는 태그 찾기
soup.find_all("p")	# 모든 태그 찾기

find, find_all 메소드를 이용하여 HTML 태그 추출

 

find는 추출한 HTML 태그 하나를, find_all은 HTML 태그를 여러 개 담고 있는 리스트를 얻는다.

 

예시코드

print(soup.find("p"))
print(soup.find_all("p"))

# 출력 결과
<p></p>
[<p></p>, <p></p>, ... , <p></p>]

 

<!DOCTYPE html> ...
<body>
  <div class="cheshire">
    <p>Don't crawl this.</p>
</div>
<div class="elice">
    <p>Hello, Python Crawling!</p>
  </div>
</body>

div 태그 중, 클래스elice인 것만 추출하려면 어떻게 해야 할까?

soup.find("div")
soup.find("div", class_="elice")

class_ 매개변수에 값을 저장함으로써 특정 클래스가 가진 태그를 추출할 수 있다.

soup.find("div", class_="elice").find("p")

 

find로 얻은 결과도 BeautifulSoup 객체이다.

따라서 find를 한 결과에 또 find를 적용할 수 있다..

위코드는 div태그안에있는 p태그를추출한다..

 

soup.find("div", class_="elice").find("p").get_text()

 

BeautifulSoup 객체에 get_text 메소드를 적용하면 태그가 갖고 있는 텍스트를 얻을 수 있다.

예시 코드

print(soup.find("p"))
print(soup.find("p").get_text())

# 출력 결과
<p>Hello, Python Crawling!</p> 
Hello, Python Crawling!
soup.find("div")
soup.find("div", id="elice")

 

특정 id의 값을 추출하고자 하는 경우에는 id 매개변수의 값을 지정할 수 있다.


Requests

requests 라이브러리

Python에서 HTTP 요청을 보낼 수 있는 모듈

HTTP 요청이란?

  • GET 요청: 정보를 조회하기 위한 요청
    (예 : 네이버 홈페이지에 접속한다. 구글에 키워드를 검색한다.)
  • POST 요청: 정보를 생성, 변경하기 위한 요청
    (예 : 웹 사이트에 로그인한다. 메일을 삭제한다.)

본 과목에서는 GET 요청만 사용

requests 라이브러리

url = "https://www.google.com"
result = requests.get(url)

 

지정한 URLGET 요청을 보냈고, 서버에서는 요청을 받아 처리한 후 result 변수에 응답을 보낸다.

print(result.status_code)
print(result.text)

 

응답의 status_code로는 요청의 결과를 알 수 있다.

만약 요청이 성공했다면
text로 해당 웹 사이트의 HTML을 얻을 수 있다.

두 라이브러리 조합하기

import requests
from bs4 import BeautifulSoup

soup = BeautifulSoup(result.text, "html.parser")

 

requestsBeautifulSoup를 조합하여 웹 페이지의 HTML을 분석할 수 있다.


실전 크롤링

배운 내용으로 크롤링 코드를 직접 작성한다.

 

웹 페이지에서 F12 버튼을 눌러 개발자 도구를 켤 수 있다.

검색을 원하는 요소에 오른쪽 마우스를 클릭하고, '검사'를 누럴 개발자 도구를 킬 수 있다.

네이버 헤드뉴스 찾기

네이버의 헤드뉴스 부분을 크롤링하고자 한다.

 

해당 부분을 포함하는 태그와 클래스를 참조하여 정보를 크롤링 하라.

import requests
from bs4 import BeautifulSoup


def crawling(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    result = []
    
    div = soup.find("div", class_="list_issue")
    
    for a in div.find_all("a"):
        result.append(a.get_text())
    
    return result
    

def main() :
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    url = "http://www.naver.com"
    req = requests.get(url, headers = custom_header)
    soup = BeautifulSoup(req.text, "html.parser")

    # crawling 함수의 결과를 출력합니다.
    print(crawling(soup))


if __name__ == "__main__" :
    main()

연합뉴스 속보 기사 제목 추출하기

네이버에 있는 연합뉴스 속보 기사들의 제목을 크롤링

 

연합뉴스 속보 기사의 제목은 find 함수로 찾은 요소 안에서 또 find를 사용해야 할 수도 있다.

import requests
from bs4 import BeautifulSoup

def crawling(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    result = []
    
    div = soup.find("div", class_="list_body")
    
    for a in div.find_all("a"):
        result.append(a.get_text())
    
    return result
    
    


def main() :
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    url = "https://news.naver.com/main/list.nhn?mode=LPOD&mid=sec&sid1=001&sid2=140&oid=001&isYeonhapFlash=Y"
    req = requests.get(url, headers = custom_header)
    soup = BeautifulSoup(req.text, "html.parser")

    # crawling 함수의 결과를 출력합니다.
    print(crawling(soup))


if __name__ == "__main__" :
    main()

bugs 실시간 음원차트 순위 추출하기

음원 사이트 bugs의 실시간 차트를 크롤링하여 높은 순위부터 차례대로 곡명을 출력

 

아마 텍스트를 그냥 출력하면 위와 같이 개행문자가 끼어 있을 것이다.

 

실습에서는 위와 같이 필요 없는 문자는 모두 필터링하려고 한다.

import requests
from bs4 import BeautifulSoup

def crawling(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    result = []
    
    tbody = soup.find("tbody")
    for p in tbody.find_all("p", class_="title"):
        result.append(p.get_text().replace('\n', ""))
    
    return result
    
    


def main() :
    custom_header = {
        'referer' : 'https://music.bugs.co.kr/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    url = "https://music.bugs.co.kr/chart"
    req = requests.get(url, headers = custom_header)
    soup = BeautifulSoup(req.text, "html.parser")

    # crawling 함수의 결과를 출력합니다.
    print(crawling(soup))


if __name__ == "__main__" :
    main()

영화 후기 수집하기

네이버 영화 페이지에 있는 영화평의 제목을 수집하여 출력

 

경우에 따라서 find 함수를 3중으로 사용해야 할 수도 있으니 데이터를 담고 있는 태그를 잘 확인하라.

import requests
from bs4 import BeautifulSoup

def crawling(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    ul = soup.find("ul", class_="rvw_list_area")
    
    result = []
    for li in ul.find_all("li"):
        result.append(li.find("strong").get_text())
        
    return result
    


def main() :
    custom_header = {
        'referer' : 'https://movie.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    url = "https://movie.naver.com/movie/bi/mi/review.nhn?code=168058#"
    req = requests.get(url, headers = custom_header)
    soup = BeautifulSoup(req.text, "html.parser")

    # crawling 함수의 결과를 출력합니다.
    print(crawling(soup))


if __name__ == "__main__" :
    main()

커뮤니티 댓글 수집하기

커뮤니티 사이트의 댓글을 수집하여 출력하고자 한다.

크롤링해온 데이터에는 개행 문자와 탭 문자가 끼어 있다.

bugs 실습때와 마찬가지로, 필요 없는 문자는 모두 필터링하려고 한다.

import requests
from bs4 import BeautifulSoup

def crawling(soup) :
    # soup 객체에서 추출해야 하는 정보를 찾고 반환하세요.
    dd_list = soup.find_all("dd", class_="usertxt")
    
    result=[]
    
    for dd in dd_list :
        result.append(dd.get_text().replace("\n", "").replace("\t", ""))
    
    return result


def main() :
    custom_header = {
        'referer' : 'https://pann.nate.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    url = "https://pann.nate.com/talk/350939697"
    req = requests.get(url, headers = custom_header)
    soup = BeautifulSoup(req.text, "html.parser")

    # crawling 함수의 결과를 출력합니다.
    print(crawling(soup))


if __name__ == "__main__" :
    main()
반응형

댓글