네트워크 연결
웹 스크레이핑은 브라우저를 열었을 때 거치는 HTML구조, CSS 스타일, 자바스크립트 실행, 이미지 렌더링을 거치지는 과정을 없앨 뿐만 아니라 가끔은 네트워크 연결 수준에서 없애야 할 때가 있습니다. 그러므로 다음 예제를 통해 브라우저로 정보를 가져오는 구조에 대해 감을 잡을 필요성이 있습니다.
밥이 데스크톱 컴퓨터를 가지고 엘리스의 서비스를 연결하는 상황
- 밥의 컴퓨터는 1과 0으로 되는 비트 스트림을 보내니다. 각 비트는 전압으로 구별됩니다. 이들 비트는 정보를 구성하며, 헤더와 바디도 그런 정보에 포함됩니다. 헤더에는 바로 다음 목표인 밥의 라우터 MAC 주소와 최종 목표인 앨리스의 IP 주소가 들어있습니다. 바디에는 밥이 앨리스의 서버 애플리케이션에 요청하는 내용이 들어있습니다.
- 밥의 라우터는 이들 비트를 받아 밥의 MAC 주소에서 앨리스의 IP 주소로 가는 패킷으로 해석합니다. 밥의 라우터의 고유 IP주소를 패킷에 'from' 주소로 기록한 다음 밥의 라우터는 이 패팃을 인터넷에 보냅니다.
- 밥의 패킷은 여러 중간 서버를 거치며 이동합니다. 중간 서버들은 정확한 물리적 경로 또는 유선 경로를 거쳐 앨리스의 서버를 향해 패킷을 보냅니다.
- 앨리스의 서버는 자심의 IP 주소에서 그 패킷을 받습니다.
- 앨리스의 서버는 헤더에서 패킷 포트의 목적지 정보를 읽고 패킷을 적합한 애플리케이션, 즉 웹 서버 애플리케이션에 보냅니다. 웹 애플리케이션에서 패킷 포트의 목적지는 거의 항상 80 포트입니다. IP 주소가 거리 주소라면 포트 번호는 아파트의 동호수라 생각해도 됩니다.
- 웹 서버 애플리케이션은 서버 프로세서에서 데이터 스트림을 받습니다. 이 데이터에는 다음과 같은 정보가 들어 있습니다.
- 이 요청은 GET 요청임
- 요청하는 파일은 index.html 임
- 웹 서버는 해당하는 HTML 파일을 찾고 새패킷으로 묶어서 자신의 라우터를 통해 밥의 컴퓨터로 전송합니다. 웹 서버가 보낸 패킷은 밥이 보낸 패킷과 같은 과정을 거쳐 밥의 컴퓨터에 도달합니다.
위 과정에서 브라우저는?
아무 곳에도 개입하지 않았습니다. 웹 브라우저는 이들 패킷을 만들고, 운영체제를 통해 패킷을 보내고, 돌아온 데이터를 해석해 사진, 소리, 비디오, 텍스트 등으로 표현할 것입니다.
웹 브라우저 역시 코드일 뿐이고, 코드는 떼어내서 기본 구성요소로 나누고, 다시 만들고, 재사용 하고, 원하는 어떤 것으로든 바꿀 수 있습니다. 웹 브라우저는 프로세서에 명령을 내려 데이터를 애플리케이션에 보내서 유/무선 인터페이스로 처리할 수 있으며, 파이썬 코드로는 단 세 줄로 수행할 수 있습니다.
from urllib.request import urlopen
html = urlopen('http://pythonscraping.com/pages/page1.html')
print(html.read())
BeaurifulSoup
BeaurifulSoup는 잘못된 HTML을 수정하여 쉽게 탐색할 수 있는 XML 형식으 파잇너 객체로 변환하므로 골치 아픈 웹을 탑색할 때 유용합니다.
from urllib.request import urlopen
form bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bs = BeaurifulSoup(html.read(), 'html.parser')
print(bs.h1)
- 요소를 읽어올 때 HTML 태그를 통해 찾는다면 중복된 요소에 대해 제일 첫번째 요소를 반환합니다.
- bs의 첫 번째 매개변수는 HTML 택스트, 두 번째 매개변수는 구문 분석기 입니다.
- 가장 널리 쓰이는 구문 분석기 중 하나는 lxml(http://lxml.de/parsing.html) 입니다.
- lxml은 지저분한 HTML 코드를 분석할 때 유용하지만, 서드파티 C 언어 라이브러리가 있어야 제대로 동작합니다.
- 잘못 만들어진 HTML 이나 손으로 쓴 HTML 을 분석해야 한다면 html5lib도 좋은 선택이 드릴 수 있습니다(html.parser 보다 느립니다.)
신뢰할 수 있는 연결과 예외처리
웹 스크레이핑에서 좌절할 수 있는 경험 중 하나는 스크레이퍼를 실행데이터를 실행 해놓고 잠든 이후, 스크레이퍼가 예기치 못한 데이터 형식에 부딪혀 에러를 일으키고 멈춰있을 때 입니다. 그러므로 예외상황에 대한 처리를 잘 해야합니다.
- 페이지를 찾을 수 없을 경우 예외처리
HTTP 에러가 반환 될 것입니다. 404, 500
from urllib.request import urlopen
from urllib.request import HTTPError
try:
html = urlopen('http://www.pythonscraping.com/pages/error.html')
except HTTPError as e:
print(e)
else:
# except 절에서 return 혹은 break을 사용했다면 이 else 문은 필요 없습니다.
- URL 해석에서 오류가 생긴경우
from urllib.request import urlopen
from urllib.error import HTTPError
from urllib.error import URLError
try:
html = urlopen('http://pythonscrapingthisurldoesnotexist.com')
except HTTPError as e:
print(e)
except URLError as e:
print('Tue server coul not be found!')
else:
print('It Worked!')
- 존재하지 않은 태그에 접근할 경우
이런 경우 BeaurifulSoup는 None 객체를 반환합니다. 문제는 None 객체 자체에 태그가 있다고 가정하고 그 태그에 접근하려하면 AttributeError가 일어나는 것입니다. 이런 상황에서 가장 쉽게 문제를 해결하는 방법은 명시적으로 체크하는 겁니다.
try:
badContent = bs.nonExistingTag.anotherTag
except AttributeError as e:
print(e)
else:
if badContent == None:
print("Tag was not found")
else:
print(badContent)
정리
웹 스크래핑을 위해 다른 서버에 요청을 보내 데이터를 가져와 브라우저에서 보여주는 과정을 이해할 필요성이 있으며, python의 Beautiful4는 이 과정을 간단하게 구현할 수 있게 도와줍니다. 이 과정에서 여러 오류에 대한 예외처리는 필수며, 중복되는 예외처리에 대해 캡슐화를 고려할 필요성이 있습니다.
Reference
Web Scraping with Python: 라이언 미첼
'IT > Scraping' 카테고리의 다른 글
웹 크롤링 모델: 링크를 통한 사이트 크롤링 (0) | 2025.02.16 |
---|---|
웹 크롤러 모델: 검색을 통한 사이트 크롤링 (0) | 2025.02.14 |
웹 크롤링 모델: 객체 계획 및 정의와 다양한 웹사이트 레이아웃 다루기 (0) | 2025.02.14 |
크롤링 시작하기 (0) | 2025.02.14 |
복잡한 HTML페이지를 분석하여 원하는 정보만 추출하기 (0) | 2025.01.28 |