TIL 3주차: 웹 스크래핑(크롤링)

iris·2020년 8월 15일
0

웹 스크래핑

1. 웹 스크래핑이란?

  • 웹 스크래핑이란 웹 페이지에서 우리가 원하는 부분의 데이터를 수집해오는 것
  • 구글 검색시에는 web scraping으로 검색해야 함
  • 참고:
    크롤링과 웹 스크래핑의 차이

2. 웹 스크래핑 해보기

2.1 네이버 영화 정보를 스크래핑할 예정

2.1.1 패키지 설치

  • beautifulsoup4 는 HTML 코드를 쉽게 스크래핑해오기 위한 도구
  • beautifulsoup4를 설치

2.1.2 스크래핑 기본 세팅

  • 폴더를 만들어 movie_scraping.py로 파일을 만들고 아래의 코드 복붙
import requests
from bs4 import BeautifulSoup

# 타겟 URL을 읽어서 HTML를 받아오고,
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20200716',headers=headers)

# HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦
# soup이라는 변수에 "파싱 용이해진 html"이 담긴 상태가 됨
# 이제 코딩을 통해 필요한 부분을 추출하면 된다.
soup = BeautifulSoup(data.text, 'html.parser')

#############################
# (입맛에 맞게 코딩)
#############################

2.1.3 영화제목을 가져오며 select/select_one의 사용법 익히기

태그 안의 텍스트를 찍고 싶을 땐 → 태그.text
태그 안의 속성을 찍고 싶을 땐 → 태그['속성']

import requests
from bs4 import BeautifulSoup

# URL을 읽어서 HTML를 받아오고,
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20200716', headers=headers)

# HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦
soup = BeautifulSoup(data.text, 'html.parser')

# select를 이용해서, tr들을 불러오기
movies = soup.select('#old_content > table > tbody > tr')

# movies (tr들) 의 반복문을 돌리기
for movie in movies:
    # movie 안에 a 가 있으면,
    a_tag = movie.select_one('td.title > div > a')
    if a_tag is not None:
        # a의 text를 찍어본다.
        print(a_tag.text)
  • beautifulsoup 내 select에 미리 정의된 다른 방법을 알아봅니다

    # 선택자를 사용하는 방법 (copy selector)
    soup.select('태그명')
    soup.select('.클래스명')
    soup.select('#아이디명')
    
    soup.select('상위태그명 > 하위태그명 > 하위태그명')
    soup.select('상위태그명.클래스명 > 하위태그명.클래스명')
    
    # 태그와 속성값으로 찾는 방법
    soup.select('태그명[속성="값"]')
    
    # 한 개만 가져오고 싶은 경우
    soup.select_one('위와 동일')
  • 항상 정확한 것은 아니나, 크롬 개발자 도구를 참고할 수도 있음

  1. 원하는 부분에서 마우스 오른쪽 클릭 → 검사
  2. 원하는 태그에서 마우스 오른쪽 클릭
  3. Copy → Copy selector로 선택자를 복사할 수 있음

3. 웹 스크래핑 팁

  • 웹 스크래핑은 웹 페이지 구조에 따라 조금씩 방법이 다르기 때문에 처음에는 좀 까다롭게 느껴질 수 있음
  • 필요할 때마다 bs4 함수를 검색하여 활용

스크래핑 팁 3가지

  • 문제분석(화면분석)
    원하는 데이터가 화면 어디에 있는지 확인.
  • 부모 요소부터 접근
    내가 원하는 데이터의 부모(조상)요소부터 가져오기. 부모요소부터 찾다보면 규칙을 찾을 수 있을 것.
  • 값 출력하기
    값을 제대로 가져오고 있는지 중간중간 출력(print)

4. 문제뱅크

4.1 네이버 영화 정보 가져오기(난이도:⭐️⭐️⭐️)

  • 주어진 네이버 영화 URL을 수정해 2018년 3월 27일 기준 네이버 영화 순위, 제목, 평점 정보를 스크래핑하여 출력하시오
  • Answer
import requests
from bs4 import BeautifulSoup

# 타겟 URL을 읽어서 HTML를 받아오고,
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20180327', headers=headers)

# HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦
# soup이라는 변수에 "파싱 용이해진 html"이 담긴 상태가 됨
# 이제 코딩을 통해 필요한 부분을 추출하면 된다.
soup = BeautifulSoup(data.text, 'html.parser')

# select를 이용해서, tr들을 불러오기
movies = soup.select('#old_content > table > tbody > tr')

# movies (tr들) 의 반복문을 돌리기
for movie in movies:
    # movie 안에 a 가 있으면,
    a_tag = movie.select_one('td.title > div > a')
    if a_tag is not None:
        # a의 text를 찍어본다.
        rank = movie.select_one('td:nth-child(1) > img')['alt']  # img 태그의 alt 속성값을 가져오기
        title = a_tag.text  # a 태그 사이의 텍스트를 가져오기
        star = movie.select_one('td.point').text  # td 태그 사이의 텍스트를 가져오기
        print(rank, title, star)

4.2 네이버 한국 야구 순위 가져오기(난이도:⭐️⭐️⭐️)

import requests
from bs4 import BeautifulSoup

# 타겟 URL을 읽어서 HTML를 받아오고,
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://sports.news.naver.com/kbaseball/record/index.nhn?category=kbo', headers=headers)

# HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦
# soup이라는 변수에 "파싱 용이해진 html"이 담긴 상태가 됨
# 이제 코딩을 통해 필요한 부분을 추출하면 된다.
soup = BeautifulSoup(data.text, 'html.parser')

# select를 이용해서, 팀순위 표를 가져오기
ranking_table = soup.select('#regularTeamRecordList_table > tr')
# print(ranking_table)

# ranking_table (tr들) 의 반복문을 돌리기
for ranking_info in ranking_table:
    # print('######', ranking_info)
    rank = ranking_info.select_one('th > strong').text
    name = ranking_info.select_one('td.tm > div > span').text

    print(rank, name)

4.3 네이버 영화 정보 가져오기(난이도:⭐️⭐️⭐️⭐️)

import requests
from bs4 import BeautifulSoup

# 타겟 URL을 읽어서 HTML를 받아오고,
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://sports.news.naver.com/kbaseball/record/index.nhn?category=kbo', headers=headers)

# HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦
# soup이라는 변수에 "파싱 용이해진 html"이 담긴 상태가 됨
# 이제 코딩을 통해 필요한 부분을 추출하면 된다.
soup = BeautifulSoup(data.text, 'html.parser')

# select를 이용해서, 팀순위 표를 가져오기
ranking_table = soup.select('#regularTeamRecordList_table > tr')
# print(ranking_table)

# ranking_table (tr들) 의 반복문을 돌리기
for ranking_info in ranking_table:
    # print('######', ranking_info)
    rank = ranking_info.select_one('th > strong').text
    name = ranking_info.select_one('td.tm > div > span').text
    win_rate = ranking_info.select_one('td:nth-child(7) > strong').text

    # 문자열(string) 을 부동소숫점형(float)으로 강제 형변환
    if float(win_rate) > 0.5:
        print(rank, name, win_rate)

스크래핑은 여전히 어렵군요 😥

1개의 댓글

comment-user-thumbnail
2021년 4월 9일

와 진짜 태그 사이에 있는 텍스트 가져오는거 찾느라 진짜 네시간은 쓴거 같은데 진자 너무너무 감사해요ㅠㅠㅠㅠ

답글 달기