일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- web
- geth
- ERC20
- ERC165
- blockchain
- 블록체인
- server
- tcp
- 제어의역전
- 네트워크
- 스마트 컨트랙트
- Programming
- 이더리움
- Python
- ethers
- web3.js
- JavaScript
- NFT
- web3
- truffle
- erc721
- git
- Docker
- Ethereum
- MySQL
- erc
- 솔리디티
- 트랜잭션
- github
- solidity
- Today
- Total
멍개의 연구소
크롤러 개발 라이브러리, 프레임워크 본문
크롤러는 주로 파이썬을 통해개발을 합니다.
javascript에서도 chreeio와 같이 크롤러를 할 수 있도록 해주는 라이브러리가 있으나, 비동기 적인 특성 때문에 코드의 작성이 상당히 어려운 부분이 있습니다.
그래서 다양한 라이브러리 제공하는 파이썬을 많이 사용합니다.
크롤러는 크게 2종류의 모듈을 사용합니다.
1. 웹 페이지 요청하는 모듈
2. 요청후 응답 받은 html 돔을 제어 할 수 있는 모듈(파서)
파이썬에서는 웹 페이지 요청을 하는 라이브러리로 requests와 urllib를 사용을 합니다.
파서 모듈로 BeautifulSoup(bs4)를 사용합니다.
우선 requests와 urllib는 요청하는건 같은데 내부적으로 텍스트를 처리하는 방식, 에러를 처리하는 방식이 다릅니다.
urllib의 404 에러 처리하는 방법
1 2 3 4 5 6 7 8 9 10 | from urllib.request import urlopen as rq url = '' try: page = rq(url) print(page.code) soup1 = BeautifulSoup(page, 'lxml') except urllib.error.HTTPError: print('404 error') | cs |
requests의 404 에러 처리하는 방법
1 2 3 4 5 6 7 8 9 10 11 | import requests as rq url = '' page = rq(url) res_code = page.code soup1 = BeautifulSoup(page.text, 'lxml') if(res_code == 404): print('404 error') | cs |
urllib는 404를 except처리를 해버립니다.
왜 굳이 저렇게 했는지는 잘 모르겠는데... 저게 은근히 귀찮더군요
그리고 두 모듈을 텍스트 인코딩 방식도 다릅니다.
기본적으로 charset이 utf-8 방식은 크게 문제가 없는데, EUC-KR방식으로 인코딩이 된 사이트는 requests로 요청을 보내면 한글이 전부 깨지는 현상이 있습니다.
이럴 땐 urllib를 사용하면 한글을 깨지지 않은 상태로 응답을 받게 됩니다.
urllib가 requests모듈보다 좀더 로우단 모듈이기 때문에 에러 처리를 함에 있어서 좀더 신경을 써주어야 하는 단점이 있습니다.
덕분에 코드의 depth가 1~2개정도 더 들어갈 수 있습니다.
이렇게 요청을 보내서 응답을 받으면,
파서를 통해 텍스트를 돔제어를 할 수 있도록 해주어야 합니다.
bs4 라이브러리를 사용을 하게 됩니다.
근데 이게 쓰다보니 치명적인 버그가 있는데요....
bs4.BeautifulSoup은 두개의 인자를 받게 됩니다.
첫번째 인자로는 돔을 제어 할 텍스트, 즉 응답받은 텍스트를 넣으면 됩니다.
두번째 인자로는 파서를 넣게 되는데 가장 많이 쓰는것은 lxml, html5lib를 사용하게 됩니다.
이게 쓰다보니 lxml과 html5lib가 어떻게 파싱을 하는지는 잘 모르겠는데 두개 모두 군데군데 파서가 잘 안될때가 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <ul class="u1"> <img src="/test_0.jpg" />1 <img src="/test_1.jpg" />2 <img src="/test_2.jpg" />3 <img src="/test_3.jpg" />4 <img src="/test_4.jpg" />5 <img src="/test_5.jpg" />6 </ul> <ul> 어쩌구 저쩌구 </ul> <script> script 어쩌구 <script> | cs |
위와 같이 되있는 텍스트를 파서를 돌리면
1 2 3 4 5 6 7 8 9 10 11 12 13 | <ul class="u1"> <img src="/test_0.jpg" />1 <img src="/test_1.jpg" />2 <img src="/test_2.jpg" />3 <img src="/test_3.jpg" />4 <img src="/test_4.jpg" />5 <img src="/test_5.jpg" />6 script 어쩌구 저쩌구 어쩌구 저쩌구 </ul> | cs |
이런 식으로 파서가 되는 경우가 발생 합니다.
스크립트 내용이 바디안으로 들어가서 tag들을 혼동을 주기도 합니다.
이럴땐 BeautifulSoup으로 나온 결과를 스트링으로 바꾸어서 다시 파서를 돌려야 합니다.
1 2 | soup = BeautifulSoup(page, 'lxml') BeautifulSoup(soup.text) or BeautifulSoup(soup.read()) | cs |
위와 같이 해주면 됩니다.
이건 해당 모듈의 문제로 어쩔 수 없는 부분이라 만약에 데이터가 파싱이 안되면 위 처럼 다시 파서를 돌려서 처리를 해야 할 것 같습니다.
파이썬에서는 scrapy라는 프레임 워크를 제공을 합니다.
scrapy를 통해 프로젝트를 생성을 하면
와 같이 디렉토리가 생성이 되는데
위에서 mung은 프로젝트 명입니다.
프로젝트로 들어가면
items.py, middlewares.py, pipelines.py, settings.py, /spider가 생성이 됩니다
items.py는 수집 하고자 하는 데이터의 모델을 만듭니다.
middlewares.py는 데이터가 저장 되기 전에 정규화를 하는 과정이라고 보면 됩니다.
pipelines은 데이터를 저장하는 곳 입니다. 디비로 저장을 하거나 파일로 저장을 하거나 합니다.
setting.py는 크롤러의 설정 파일인데 각종 설정들을 변경을 해줍니다.
기본적으로 scrapy 프로젝트를 만들어서 크롤러를 실행하면 각종 로그가 찍히게 됩니다 이럴땐
LOG_LEVEL = 'WARNING'
를 추가를 하면 쓸데없는 로그가 찍히지 않게 됩니다.
다음으로는 실질적으로 데이터를 수집을 하는 부분인 /spider 디렉토리입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import scrapy from bs4 import BeautifulSoup class DmozSpider(scrapy.Spider): name = "m" start_urls = [ 'url' ] def parse(self, response): title = response.xpath('//h3[@class="tit-prd"]/text()').extract() print(title) title = response.css('div h2').extract() print(title) for sel in response.xpath('//select'): title = sel.xpath('option/text()').extract() soup = BeautifulSoup(response.text, 'html5lib') | cs |
$ scrapy crawl m
위처럼 scrapy crawl [name]을 주면 해당 크롤러를 동작시킬 수 있습니다. 그러면 start_urls의 링크들을 접속을 하여 해당응답 객체를 parse의 두번째 인자로 콜백을 합니다.
scrapy는 xpath방식을 이용하여 돔을 제어를 하지만 css selector방식을 이용하여 돔을 제어를 할 수 있습니다. 개인적으로는 후자가 더 편한 것 같습니다. 전자는 뭔가 정감이 가지 않더군요 ㅋㅋㅋㅋ
위의 내용들은 사소해 보일 수 있는 부분들인데 저것들이 갑자기 터지면 은근히 시간을 엄청 잡아먹는 부분들 입니다. 하나하나 해결하는데 몇날 몇일씩 걸렸던것 같네요 많게는 거의 몇달동안 해결이 안된 것들도 있었고... ㅋㅋ
그럼이만~
'서버 > 크롤러' 카테고리의 다른 글
image download (0) | 2017.05.10 |
---|