Python

Lyoka료카·2023년 3월 29일
0

python 자료

목록 보기
3/3

1. Python Web Scraping

웹사이트에서 HTML을 읽어 필요한 데이터를 긁어오는 것을 Web Scraping이라 한다.
이 과정을 크게 웹페이지를 읽어오는 과정과
읽어온 HTML 문서에서 필요한 데이터를 뽑아내는 과정으로 나뉠 수 있다.

웹페이지를 읽어오는 일은 여러 모듈을 사용할 수 있는데, 파이썬에서 기본적으로 제공하는 urllib, urllib2 을 사용하거나 편리한 HTTP 라이브러리로 많이 쓰이고 있는 requests 를 설치해 사용할 수 있다.


requests - 웹페이지 읽어오기

requests를 사용하려면 pip를 이용하여 패키지를 설치한다.

pip3 install requests #pip는 Python 버전에 맞게 설정한다.(pip,pip3)

기본적인 requests 기능을 먼저 살펴보면
requests는 HTTP GET, POST, PUT, DELETE 등을 사용할 수 있으며
편리한 데이터 인코딩 기능을 제공한다.
즉 데이터를 Dictionary로 만들어 get, post 등에서 사용하면 필요한 request 인코딩을 자동 처리해 준다.

예제)

import requests
 
# GET
resp = requests.get('http://httpbin.org/get')
print(resp.text)
 
# POST
dic = {"id": 1, "name": "Kim", "age": 10}
resp = requests.post('http://httpbin.org/post', data=dic)
print(resp.text)
 
resp = requests.put('http://httpbin.org/put')
resp = requests.delete('http://httpbin.org/delete')

requests.get(url) 함수를 사용하면 해당 웹페이지 호출 결과를 가진 Response 객체를 리턴한다.
Response 객체는 HTML Response와 관련된 여러 attribute들을 가지고 있는데

예를 들어
Response의 status_code(상태 코드)속성을 체크하여 HTTP Status 결과를 체크할 수 있고,
Response에서 리턴된 데이터를 문자열로 리턴하는 text 속성이 있으며,
Response 데이터를 바이트(bytes)로 리턴하는 content 속성등이 있다.

만약 Response에서 에러가 있을 경우 프로그램을 중단하도록 할 때는
Response 객체의 raise_for_status() 메서드를 호출할 수 있다.

HTML 문서를 가져와 출력하는 예제)

import requests
 
resp = requests.get( 'http://daum.net' )
# resp.raise_for_status()
 
if (resp.status_code == requests.codes.ok):
    html = resp.text
    print(html)

requests에서의 한글 깨짐 문제

requests에서 웹 호출을 진행한 후 결과는 Response 객체에 담기게 되는데
Response의 text 속성은 str 클래스 타입으로서 보통 requests 모듈에서 자동으로 데이터를 인코딩해 준다.

requests는 HTTP 헤더를 통해 결과 데이터의 인코딩 방식을 추측하여 Response 객체의 encoding 속성에 그 값을 지정하고 text 속성을 엑세스할 때 이 encoding 속성을 사용한다.

만약 인코딩 방식을 변경해야 한다면
text 속성을 읽기 전에 Response의 encoding 속성을 변경하면 된다.

실제 예시
네이버 홈페이지는 한글 출력에 문제가 없지만
네이버 증권사이트 웹페이지는 한글이 깨져 보이게 된다.
원인

네이버 홈페이지는 UTF-8을 사용하고
네이버 증권사이트는 ISO-8859-1을 사용하고 있다.

encoding 확인하는 예제)

import requests

resp = requests.get('http://naver.com')
print(resp.encoding)
'UTF-8'
resp = requests.get('http://finance.naver.com')
print(resp.encoding)
'euc-kr'

인코딩이 유니코드 인코딩(예: UTF-8 등) 이거나 한글 인코딩(예: EUC-KR)이면 일반적으로 한글이 깨지지 않지만, 영문 인코딩이라면 한글이 깨지게 된다.

이를 해결하는 방법은 미리 Response 객체의 encoding을 한글인코딩(예: EUC-KR)이나 None(인코딩 추측을 하지 않도록) 으로 지정 후, text속성을 읽으면 된다.

한글이 안 깨지게 변경하는 예제)

import requests
 
resp = requests.get('http://finance.naver.com/')
resp.raise_for_status()
 
resp.encoding=None   # None 으로 설정
#resp.encoding='euc-kr'  # 한글 인코딩
 
html = resp.text
print(html)

UTF-8

UTF-8은 가장 많이 사용되는 가변 길이 유니코드 인코딩이다.
UTF-8로 표현 가능한 길이는 최대 6바이트지만 다른 인코딩과의 호환을 위해 4바이트까지만 사용한다. 그래서 한 글자가 1~4바이트 중 하나로 인코딩될 수 있으며, 1바이트 영역은 아스키 코드와 하위 호환성을 가진다.


BeautifulSoup - 웹페이지 파싱

웹페이지 HTML 문서를 파싱(Parsing)하기 위해서는 BeautifulSoup 라는 모듈을 사용할 수 있다. 먼저 BeautifulSoup를 설치한다.

pip3 install beautifulsoup4

BeautifulSoup를 사용하기 위해서는 먼저 BeautifulSoup 모듈을 import하여야 하는데 모듈명은 bs4 이다.
bs4 모듈이 import 된 후, bs4.BeautifulSoup(HTML문서) 생성자를 호출하여 BeautifulSoup 객체를 생성한다.

BeautifulSoup 객체를 생성 예시)

import bs4
 
html = "<html><body>...생략...</body></html>"
bs = bs4.BeautifulSoup(html, 'html.parser')

BeautifulSoup 객체에서 특정 HTML 태그들을 찾기 위해 select() 메서드를 사용한다.
이 메서드는 파라미터로 어떤 태그들을 찾을 지를 css 스타일의 selector로 지정하면 된다.

예를 들어, select('.news li') 는 news 라는 CSS 클래스 안이 모든 li 태그들을 리턴하게 된다.

리턴된 결과는 태그들의 리스트(list) 인데, 각 태그 요소로부터 태그내 문자열을 리턴하기 위해서는 getText()를, 특정 태그 attribute를 얻기 위해서는 get('attribute명') 메서드 등을 사용할 수 있다.

네이버 증권사이트에서 주요 Top 뉴스 제목을 발췌하는 예제)

# -*- coding: utf-8 -*-
 
import requests, bs4
 
resp = requests.get('http://finance.naver.com/')
resp.raise_for_status()
 
resp.encoding='euc-kr'
html = resp.text
 
bs = bs4.BeautifulSoup(html, 'html.parser')
tags = bs.select('div.news_area h2 a') # Top 뉴스
title = tags[0].getText()
print(title)

HTTP 상태 코드(Status code)란?

사용자가 웹 브라우저를 통해 웹 서버에 어떠한 요청을 할 경우, 웹 서버는 요청에 대한 응답으로 아래와 같은 HTTP 상태 코드를 나타낸다.
응답은 HTTP 요청이 성공했는지 실패했는지를 서버에서 알려주는 코드에 따라 5개의 그룹으로 나누어진다.

HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜) 상태 코드를 통하여 사용자는 현재 서버에 어떠한 오류가 있는지를 확인할 수 있다.

상태 코드 종류

1.Information : 100번대(정보 응답)
2.Successful : 200번대(성공 응답)
3.Redirection : 300번대(리다이렉션 응답)
4.Client Error : 400번대(클라이언트 에러 응답)
5.Server Error : 500번대(서버 에러 응답)


profile
고딩 프로그래머

0개의 댓글