- [Python] 웹 크롤러 만들기 with Requests/BeautifulSoup2023년 04월 17일
- 조별하
- 작성자
- 2023.04.17.오후04:08
🔖 웹 크롤러란?
어떠한 정보를 브라우저에서만 보는 것뿐 아니라 내가 이용하기 편한 방식으로 보관하거나 조작하는 경우가 있다.
Python을 이용하면 간단한 코드 몇줄 만으로도 쉽게 웹 사이트에서 원하는 정보만을 가져와 다룰 수 있다.
🔖 웹에서 정보 가져오기
➤ Requests를 이용하기
python에는 requests 라는 유명한 http request라이브러리가 있다.
➤ 설치하기
pip3 install requests
from rest_framework.views import APIView from rest_framework.response import Response from pocket.models import List from pocket.serializers import ListSerializer import requests class ParseAPIView(APIView): def get(self, request): queryset = List.objects.all() serializer = ListSerializer(queryset.first()) # HTTP GET Requests req = requests.get('https://laagom.tistory.com/') # HTTP 소스 가져오기 html = req.text # HTTP Header 가져오기 header = req.headers # HTTP Status 가져오기 (200: 정상) status = req.status_code # HTTP가 정상적으로 되었는지 (True/False) is_ok = req.ok return Response(serializer.data)
위 코드에서 우리가 사용할 것은 HTML 소스를 이용하는 것이다. 따라서 html = req.text를 이용한다.
위에 나온 html, header, status, is_ok를 출력해 본 결과 제대로 요청해서 가져온 문자열을 확인할 수 있었다.
header: { 'Date': 'Mon, 07 Nov 2022 07:46:32 GMT' , 'Content-Type': 'text/html;charset=UTF-8' , 'Transfer-Encoding': 'chunked' , 'Vary': 'Accept-Encoding' , 'T_USERID': '800cdc655e5524bc59b66df34b1f68145caade80' , 'Set-Cookie': 'REACTION_GUEST=eb3148932a1f9674bf875d5d26457e0543a9abf5' , 'X-Content-Type-Options': 'nosniff' , 'X-XSS-Protection': '1; mode=block' , 'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate' , 'Pragma': 'no-cache' , 'Expires': '0' , 'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains' , 'Content-Encoding': 'gzip'} status: 200 is_ok: True
➤ BeautifulSoup 이용하기
Requests는 정말 좋은 라이브러리이지만, html을 python에서 사용할 수 있는 객체구조로 이용하기 위해서 다른 라이브러리를 사용해야 한다. 그것이 바로 BeautifulSoup이다. BeautifulSoup은 html코드를 Python이 이해하는 객체 구조로 변환하는 Parsing을 맡고 있고, 이 라이브러리를 이용해 우리는 제대로 된 정보를 추출해 낼 수 있다.
pip3 install bs4
BeautifulSoup을 직접 쳐서 설치하는 것도 가능하지만, bs4라는 wrapper라이브러리를 통해 설치하는 방법이 더 쉽고 안전하다.
➤ 이용방법
위에서 이용한 소스코드를 좀 더 다듬어 보자.
import requests from bs4 import BeautifulSoup class ParseAPIView(APIView): def get(slef, request): queryset = List.objects.all() serializer = ListSerializer(queryset.first()) # HTTP GET Requests req = requests.get('https://laagom.tistory.com/') # HTTP 소스 가져오기 html = req.text ## BeautifulSoup를 이용 # BeautifulSoup으로 html소스를 python객체로 변환 soup = BeautifulSoup(html, 'html.parser') return Response(serializer.data)
이 soup객체에서 원하는 정보를 찾아낼 수 있다.
BeautifulSoup에서는 여러 가지 기능을 제공하는데, 여기서는 select를 이용한다. select는 css selector를 이용해 조건과 일치하는 모든 객체들을 List로 반환해 준다. 예시로 내가 작성하고 있는 기술 블로그에서 a링크로 걸려있는 값을 모두 가져와 보도록 하자
현재 위의 이미지는 내가 작성하고 있는 기술블로그 현황화면이다. 여기서 개발자 도구를 열어 블로그의 모든 제목을 가져와 보려고 한다.
BeautifulSoup에서는 html요소뿐 아니라 css도 가져올 수 있기 때문에 '.index-item > .article-info > a' 에 속하는 모든 항목을 가져오면 블로그의 제목을 가져올 수 있을 것이다.
from rest_framework.views import APIView from rest_framework.response import Response from pocket.models import List from pocket.serializers import ListSerializer import requests from bs4 import BeautifulSoup class ParseAPIView(APIView): def get(slef, request): queryset = List.objects.all() serializer = ListSerializer(queryset.first()) # HTTP GET Requests req = requests.get('https://laagom.tistory.com/') # HTTP 소스 가져오기 html = req.text ## BeautifulSoup를 이용 # BeautifulSoup으로 html소스를 python객체로 변환 soup = BeautifulSoup(html, 'html.parser') my_titles = soup.select( '.index-item > .article-info > a' ) print(my_titles) return Response(serializer.data)
my_titles라는 변수에 soup객체의 select함수를 이용해 css객체에 접근해서 내가 원하는 태그와 블로그의 제목을 가지고 와봤다.
위의 base shell에서 출력한 결과는 my_titles에 담긴 목록을 그대로 보여준 거라 깔끔하지 않고 태그와 요소가 섞여 있어 보기 어렵다.
# HTTP GET Requests req = requests.get('https://laagom.tistory.com/') # HTTP 소스 가져오기 html = req.text ## BeautifulSoup를 이용 # BeautifulSoup으로 html소스를 python객체로 변환 soup = BeautifulSoup(html, 'html.parser') my_titles = soup.select( '.index-item > .article-info > a' ) # my_titles는 list객체 for title in my_titles: # Tag안의 텍스트 print(f'title = {title.text}') # Tag의 속성을 가져오기(ex: href속성) print(f'url = {title.get("href")}')
위처럼 반복문을 돌려 제목의 text와 url만 뽑아서 확인해 보자.
'LANGUAGES > Python' 카테고리의 다른 글
[Python] 파이썬 오버라이딩과 오버로딩 (0) 2023.05.16 [Python] format(천단위 콤마 삽입하기) (0) 2023.05.04 다음글이전글이전 글이 없습니다.댓글