어느정도 파이썬의 문법을 다 떼면 가장 먼저 배우게 되는, 배워야 하는 모듈일 듯 합니다.

웹크롤링이나 각 사이트에서 제공하는 API를 사용할때도 requests 모듈을 이용하게 됩니다.

 

우리(일반인)가 사용하는 인터넷은 기본적으로 사용자가 주소를 호출하면 그 주소에 맞는 html 파일을 사용자에게 보내주고 사용자는 웹브라우져로 그 html 파일을 열어 인터넷을 보게 됩니다. 정확히는 html 파일이 아니라 하나의 페이지의 html 정보를 다른 정보들와 함께 보내주고 일반인의 경우 html만 보면 됩니다.

 

인터넷에 'http request 통신'이라고 검색하면 무수한 글들이 있으니 참고하시면 됩니다.

아래는 아주 간단하고 쉽게 HTTP 통신을 설명해 놓았습니다.

 

blog.naver.com/namju1v/222228351929

 

HTTP흐름, Request & Response, https와의 차이

HTTP HyperText Transfer Protocol​컴퓨터 네트워크 계층 중에서도 사용자와 가장 접점에 있는 애...

blog.naver.com

하지만 앞서 언급한 각 대형 사이트에서 제공하는 API를 사용하기 위해서 단순하게 인터넷 주소만을 알고 요청하면 각 사이트들에서 이를 인정하지 않고 Bad request 라는 400번대의 상태(status)와 함께 정보를 보내주지(response) 않습니다. 아주 단순한 예로 정상적인 로그인 절차(아이디와 비밀번호 입력)를 거치지 않고 로그인이 된 다음의 페이지에 그냥 인터넷 주소만으로 접근한다면 bad request라 하며 접근이 불가할 것입니다.(하지만 예전에 그냥 접근이 문제없이 되기도 해서 문제가 되기도 했지요.)

 

그리고 많은 대형 사이트의 API 역시 그냥 아무나 사용할 수 있도록 열어놓은 것이 아니라 사이트 가입 + API 사용 등록을 해야 사용할 수 있습니다. 그리고 API 사용 등록을 하면 비밀키 또는 토큰(token) 이라는 이름의 복잡한 문자열을 주는데 이러한 토큰과 함께(header 값에 추가) 제공하는 API 주소에 접근을 하면 더이상 400번대의 bad request같은 response가 아닌 200번대의 성공 response를 받을 수 있습니다.

 

이번 블로그에서는 웹 크롤링을 위한 request 모듈을 사용하는 방법을 알아보겠습니다

 

 

SPOTIFY의 API 기능 중 하나는 가수 이름을 입력하면 그 가수에 대한 기본적인 정보를 보여주는 부분이 있습니다. 그리고 제 홈페이지에도 이 기능이 들어가 있습니다. 가수 정보 보기입니다.

 

하지만 맹점이 일본 가수의 경우도 일본어 이름을 입력하면 인식을 못하고 꼭 영문 이름을 쳐야 한다는 맹점이 있습니다. 우리나라 가수 역시 마찬가지이구요. 그렇기 때문에 내가 일본어로 가수명을 입력해도 영어 가수명으로 바꿔주는 신박한 기능에 대해서 생각했는데 구글 검색결과로 해결했습니다.(이것을 생각해 낸 제가 얼마나 대견스러웠는지 모릅니다.ㅎㅎ)

 

한국 구글은 한국어 발음으로 알려줍니다.
미국 구글은 영문 이름도 같이 나옵니다만 사토의 오(o) 발음을 영어에는 없는 장모음으로 했네요.. 굳이??

위의 검색결과는 각각 한국 구글과 미국 구글의 검색 결과로 미국 구글로 검색하면 이 가수의 영문명을 알 수 있습니다. 

그리고 항상 동일한 위치에 영문 이름이 위치할 것이기 때문에 거기 있는 태그를 크롤링하면 됩니다.

 

위의 결과에 따라 일본어 가수명을 입력하면 영어 가수명으로 바꿔주는 함수가 다음과 같이 나옵니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from urllib.request import Request, urlopen
import urllib.parse
from bs4 import BeautifulSoup as Soup
 
def get_spo(keyword):
    # search the artist in google, and get the english name of artist
    try:
        keyword.encode(encoding='utf-8').decode('ascii')
    except UnicodeDecodeError:
        base_url = "http://google.com/search?hl=en&q="
        url = base_url + urllib.parse.quote_plus(keyword)
        url = Request(url, headers={'User-Agent''Mozilla/5.0'})
        html = urlopen(url).read()
        soup = Soup(html, 'html.parser')
        artist_name = soup.find("h3", {"class":"zBAuLc"}).text
        print(artist_name)
cs

- 일단 필요한 module을 import합니다.

urllib.request 에서 Request는 말그대로 핵심인 request 요청을 해주는 모듈함수이고

urlopen은 불러온 url주소를 열어주는 모듈함수입니다...

그리고 urllib.parse는 한국어나 일본어를 스트링형식으로 바꿔줍니다. 

(브라우저 검색창에서는 그냥 입력해도 되던데 코딩으로 할때는 바꿔줘야 합니다.)

그리고 bs4(BeautifulSoup는 불러온 결과에서 원하는 결과만을 빼내기 위한 크롤링 작업을 위함입니다.

(통상 BeautifulSoup는 꼭 as Soup으로 사용하던데... 저도 그렇게 사용했지만 굳이...)

 

- 본격적인 함수에 들어가서 맨 처음 일본어가 아니면 굳이 이러한 과정을 거칠 필요가 없습니다. 예를 들어 Mr. Children을 입력하는 경우 일본 가수로 뜨지만 태그가 다른 일본 가수와는 달라져 버리더군요... 

그렇기 때문에 일본어가 있는 경우에만 영어 이름으로 바꾸기로 합니다.

 

- try except구문을 사용했습니다. 위의 방법은 Stack Overflow에서 찾은 방법으로 한글, 중국어, 일본어의 경우 유니코드이고 아스키 코드가 아닙니다. 아스키 코드는 단순하게 영어 알파벳과 숫자, 각종 필수적인 부호/기호들이라고 생각하면 편합니다. 그렇기 때문에 위의 명령어에서도 유추할 수 있듯이 유니코드로 인코딩 한 후 다시 아스키코드로 디코드를 하면 일본어는 에러를 발생하게 됩니다. 그러한 경우에만(except UnicodeDecodeError) 영어 가수명으로 바꿔주는 작업을 합니다.

 

- 앞서 설명했듯이 모든 http 통신은 기본적으로 인터넷 주소를 기반으로 하고 있습니다. 그리고 검색의 경우에는 주소에 덧붙여 검색어를 넣어주면 됩니다. 아래와 같이 색으로 구분지어 봤습니다.

 

http://google.com/search?hl=en&q=keyword

 

주황색: 기본적인 요청 주소입니다. (편의를 위하여 흔히 base_url이라는 이름의 변수로 저장하여 사용합니다.)

검은색: 구분자입니다.

hl=en : 미국 구글의 경우 붙여줍니다. (뭐 언어는 영어 그런뜻이지 않겠습니까.ㅎ)

q=keyword : 검색어를 입력하는 부분입니다. keyword 대신에 내가 원하는 검색어를 입력합니다. 하지만 코딩의 경우 일본어 검색어를 그대로 입력하지 않고 앞서 언급 했듯이 스트링 타입으로 변경(urllib.parse.quote_plus(keyword))해 줍니다. (quote_plus()quote()의 업그레이드 버전인가... 제가 쓰고도 모르겠네요.)

 

-그리고 다음줄에 url = Request(url, headers={'User-Agent': 'Mozilla/5.0'}) 이 핵심입니다. 사실 모든 request 요청에는 주소(url)와 header값이 함께 전달됩니다. 하지만 웹크롤링의 경우 대부분의 별도의 header를 지정해주지 않아도 요청을 받는 쪽에서 크게 문제를 제기하지 않고 API를 사용할때는 주소와 header 값에 꼭 비밀키(토큰) 번호를 주어야 문제없이 요청을 받아 response를 하게 됩니다. 그리고 이번의 경우도 사실 header값을 지정 안했다가 에러가 발생해서 인터넷을 찾아보니 위와 같이 최소한의 header값을 넣어 해결하였습니다.

 

header값은 나의 요청에 대한 배경 정보라고 보시면 되겠습니다.^^;

예를 들어 제 블로그 다른 글인 리그오브레전드 API 이용을 위한 header값은 아래와 같습니다. 보시면 실제로 웹사이트에서는 header값을 통채로 지정해 그대로 쓰게 하고 있습니다. 분명 쓸데없는 값도 있을텐데 쓰라면 써야죠.😅

 

request_headers = {

    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36",

    "Accept-Language": "en-US,en;q=0.9,ko-KR;q=0.8,ko;q=0.7",

    "Accept-Charset": "application/x-www-form-urlencoded; charset=UTF-8",

    "Origin": "https://developer.riotgames.com",

    "X-Riot-Token": "RGAPI-6840792e-23cc-4695-afbc-b4955709159a"

}

출처: https://conansjh20.tistory.com/56 [취미는 파이썬]

 

총 다섯개의 값이 들어가는데 위의 네가지 정보는 기본 배경 정보이며 마지막 X-Riot-Token이 비밀키로 핵심입니다. 그리고 통상 X-로 시작하는 것은 각 웹사이트의 고유 헤더값이라고 생각하면 됩니다.(비밀키는 이미 유효기간 지나서 상관 없습니다.ㅋㅋ)

 

 

그리고 이어서 url 변수가 곧 요청한 request에 대한 결과 페이지를 포함하고 있는 response 라고 보면 됩니다.

(html 정보 외의 다른 정보(response header 등)들도 포함하고 있을 겁니다.)

 

- 이어서 urlopen(url).read()을 이용하여 html 정보만을 뽑아내고 Soup()를 이용하여 html을 크롤링하기 좋게 파싱하고 마지막으로 내가 원하는 특정 문구에 대하여 크롤링하면 원하는 결과를 얻을 수 있습니다. 😎

 

 

 

저의 홈페이지에서 적용 예입니다.

앞서 설명한대로 주소와 구분자 ? 그리고 artist=검색어 를 입력하면 가수 정보 화면으로 이동합니다.

실제 위의 주소를 그대로 복사해서 아래 붙여 넣기 해보니 자동으로 일본어 검색어가 스트링으로 바뀌었습니다.

(자동으로 urllib.parse.quote_plus() 함수를 적용해 줍니다.)

 

conansjh20.pythonanywhere.com/artist/?artist=%E3%83%8F%E3%83%B3%E3%83%90%E3%83%BC%E3%83%88%E3%83%8F%E3%83%B3%E3%83%90%E3%83%BC%E3%83%88

 

React App

 

conansjh20.pythonanywhere.com

 

+ Recent posts