[Python] 파이썬 웹크롤링봇 만들기 -2- First Scraper

in #kr2 years ago (edited)

안녕하세요,

일주일에 한번 올리기로 하였는데 늦어 지고 말았습니다. 글쓰는것도 부지런한 노력이 필요하다는 것을 다시 한번 느낍니다.
지난주에 목차를 올려드렸던것처럼 오늘은 첫 크롤러를 만들어 보겠습니다.

스터디때 사용한 교재가 있는데요, '파이썬으로 웹 크롤러 만들기' 제목으로 출간된 책입니다.

처음 Python을 시작하는 분에게도 무리가 없는 책입니다.

1. First Scraper

이번 노트에서는 인터넷 웹서버로 request를 날려보고 응답한 데이터를 가지고 BeautifulSoup로 파싱을 해보는 시간을 가져보겠습니다.

아래 링크에 파이썬 코드 예제가 있으니 참고하시면 되겠습니다.

교재에서는 urllib 이라는 기본 라이브러리를 사용하지만, requests 라는 라이브러리를 사용해서 보다 편하게 사용할 수 있습니다.

지난 포스트에 설치하였던 Jupyter notebook 화면에서부터 시작해보겠습니다.

Jupyter Notebook 실행화면

첫줄에 아래 코드를 넣고 CTRL+ENTER 또는 ALT+ENTER키로 코드를 한줄 실행해봅니다.

from urllib.request import urlopen
html = urlopen("http://pythonscraping.com/pages/page1.html")
print(html.read())

코드의 실행화면은 아래와 같습니다.

첫 코드 실행
축하드립니다. 처음으로 파이썬 코드로 웹페이지를 불러왔습니다.

이번에는 requests 라이브러리를 통해서 웹페이지를 불러오겠습니다.

import requests
html = requests.get("http://pythonscraping.com/pages/page1.html")
print(html.text)

결과 출력문을 보시면 무엇인가 조금더 깔끔하게 출력되는것을 보실 수 있습니다.
urllib보다 편하게 쓸수가 있어 requests를 사용하는것을 추천드립니다.

출력결과를 보시면<body> <div> 와 같은 html 태그들이 붙어 있는데요, 이것들을 띠어내고 원하는 부분만을 추출할 수 있는 BeautifulSoup를 사용해 보겠습니다.

from bs4 import BeautifulSoup as bs
html = requests.get("http://pythonscraping.com/pages/page1.html")
html_text = html.text
bs_html = bs(html_text, "html.parser")
print(bs_html)

출력 결과는 앞에서 했던 print(html.text)print(bs_html)과 큰 차이는 없을 것입니다.
하지만, type으로 두 객체를 호출해보면 객체명이 다릅니다.
서로 다른 두 객체명

Python 내부적으로, bs_html로 저장되어 있는 객체는 BeautifulSoup의 데이터 형태로 저장되어 있고 print 문을 만났을때 보기 좋은 형태로 출력해주는 것입니다. 이해하기 어려워도 상관없이 넘어가도 좋습니다.

이제, 우리가 원하는 부분인 제목, 본문을 추출해보겠습니다.

조금 더 설명드리면, bs_html 이라는 객체는 requests로 불러온 html 텍스트 데이터를 BeautifulSoup에 넣으면서 BeautifulSoup가 이 html 텍스트 데이터를 파싱(해석)해서 객체에 담고 있는 상태입니다. 그래서 우리가 원하는 테그안에 있는 데이터를 꺼내올 수 있습니다.

단순히 bs_html뒤에 .tag 이름만을 붙여도 호출이 됩니다.

bs_html.title 
#<title>A Useful Page</title>

get_text() 를 붙여서 실행하면 tag들을 띄어버리고 tag내의 내용만을 출력합니다.

bs_html.title.get_text()
#'A Useful Page'

전체 bs_html객체를 태그 없이 전부 출력이 가능합니다.

print(bs_html.get_text())
#A Useful Page

An Interesting Title

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

이제, requst 라는 dict 객체를 먼저 선언하고 "title" , "content" 제목과 본문을 분리해서 넣어 보도록 하겠습니다.

result = {}

result['title'] = bs_html.title.get_text()
result['content'] = bs_html.body.div.get_text()

print(result)

result출력

python 객체인 dictionary 형태로 선언된 result에 결과가 저장되어 있습니다. 노트북을 종료하고 다시 켤때는 이 result 객체가 사라지게 됩니다.

이번에는 이걸 파일로 옮겨서 ipynb 노트북이 끝났을때도 기록이 남도록 해보겠습니다.

2. file로 읽고 쓰기

with ~ 구문으로 시작되는것은 open 과 같이 함수에서 지원을 하는 객체만 사용이 가능합니다.
with 구문이 끝나는 다음 줄에서는 호출 가능한 f를 호출할 수가 없습니다.

with open("./result.txt", 'w', encoding='utf8') as f:
    f.write("{} \n {}".format(result['title'], result['content']))

f.write 는 open으로 열은 파일을 지칭하는 f 객체에 쓰겠다는 의미입니다. 이제 노트북이 열려있는 폴더로 가보시면 result.txt 가 생성되어 있음을 확인하실 수 있습니다.

여기서 "{} \n {}" 과 같은 python formatting 이 나오는데요. 아래 짧은 예제를 보시죠.

test_a = "{} : 입니다"
print(test_a)
# {} : 입니다

로 출력이 됩니다만

print(test_a.format("여기에 변수를 포함시켜보아요")
#여기에 변수를 포함시켜보아요 : 입니다

위이 예제 처럼 string 에 변수를 집어 넣는 역할을 하는 것입니다. python 에 여러가지 formating 방법이 있는데 이 사이트를 참고하시면 좋을 것 같습니다.

코드 아카데미 python에서 연습했던 기초를 조금씩 섞어서 진행하였습니다.
기초가 중요하긴 하지만, 자신이 흥미 있는 부분을 계속 하다가 보면 저절로 문법이 익혀지니 너무 어려워 마시고 꾸준히 연습해보세요.


다음 주에는 암호화폐 대표적인 뉴스사이트 coindesk를 크롤링 해보겠습니다.