일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- map
- 콜렉션
- kotlin
- 웹크롤러
- function
- crawler
- Class
- animation
- 함수
- Yocto
- set
- textstyle
- 다트
- variable
- 크롤러
- Android
- 파이썬
- Collection
- Flutter
- 클래스
- text
- pushnamed
- 코틀린
- List
- package
- python
- import
- ML
- DART
- 플러터
- Today
- Total
조용한 담장
Scrapy : python web crawler 본문
Scrapy
파이썬으로 구현된 웹 클롤러 이다.
기본 구조와 동작을 이해하면 다양하게 활용하기 좋은 오픈소스 소프트웨어다.
구조 간단히 보기
사이트 주소를 가지고 (1)Request 하면 (4)Downloader 가 다운받아 (5)Response 를 생성해주고, (6)Response 에서 필요한 (7)Items 을 뽑아 (8)Item PIpelines 을 통해 결과를 얻어내면 된다.
Scheduler와 Engine이 있다. 자세한건 공식문서를 보자.
command line tool 로 테스트 해보기
ㅃㅃ 커뮤니티 사이트의 게시판 목록을 읽어보자.
$ scrapy shell http://www.ppomppu.co.kr/zboard/zboard.php\?id\=ppomppu4\&category\=3
2019-10-01 11:11:46 [scrapy.utils.log] INFO: Scrapy 1.7.3 started (bot: scrapybot)
...
2019-10-01 15:14:24 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.ppomppu.co.kr/robots.txt> (referer: None)
2019-10-01 15:14:24 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.ppomppu.co.kr/zboard/zboard.php?id=ppomppu4&category=3> (referer: None)
[s] Available Scrapy objects:
...
[s] request <GET http://www.ppomppu.co.kr/zboard/zboard.php?id=ppomppu4&category=3>
[s] response <200 http://www.ppomppu.co.kr/zboard/zboard.php?id=ppomppu4&category=3>
...
robots.txt 가 있으면 [s] response
가 없다.
웹브라우저의 개발자 도구를 사용해서 게시글 제목의 CSS 정보를 찾아본다.
페이지 소스를 보면 아래처럼 되어있다.
<font class=list_title>[Amazon] Logitech G29 Gaming Racing Wheel ($183.01/무료)</font>
css selector 를 사용해서 값을 얻어보자.
>>> response.css('font.list_title')
[<Selector xpath="descendant-or-self::font[@class and contains(concat(' ', normalize-space(@class), ' '), ' list_title ')]" data='<font class="list_title">[Amazon] Log...'>, <Selector xpath="descendant-or-self::font[@class and contains(concat(' ', normalize-space(@class), ' '), ' list_title ')]" data='<font class="list_title">[aliexpress]...'>
...]
list_title 을 뽑아준거 같은데 가공이 필요하다.
text 값을 얻기위해 getall() 를 써보자.
>>> response.css('font.list_title').getall()
['<font class="list_title">[Amazon] Logitech G29 Gaming Racing Wheel ($183.01/무료)</font>', '<font class="list_title">[aliexpress] 레노버 S340 15api 랩탑용 키보드 스킨 (1.79$ / Free)</font>'
...]
좀 더 정확하게 텍스트만 가져오자.
>>> response.css('font.list_title::text').getall()
['[Amazon] Logitech G29 Gaming Racing Wheel ($183.01/무료)', '[aliexpress] 레노버 S340 15api 랩탑용 키보드 스킨 (1.79$ / Free)'
...]
일단 잘 얻어진다.
이정도만 코드로 구현해보자.
Spider 구현
새 프로젝트를 만든다.
$ scrapy startproject ppboard
New Scrapy project 'ppboard', using template directory '/scrapy/venv/lib/python3.6/site-packages/scrapy/templates/project', created in:
/scrapy/ppboard
You can start your first spider with:
cd ppboard
scrapy genspider example example.com
spider 를 만든다.
name
은 spider 의 이름이다.
spider 의 최종 리턴값의 형태는 Request, BaseItem, dict or None 이다.
import scrapy
class PpboardSpider(scrapy.Spider):
name = "ppb3"
def start_requests(self):
urls = [
'http://www.ppomppu.co.kr/zboard/zboard.php?id=ppomppu4&category=3',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
list_titles = response.css('font.list_title::text').getall()
yield { 'list titles': list_titles }
spider를 실행한다.
$ scrapy crawl bbp3
2019-10-01 15:37:52 [scrapy.utils.log] INFO: Scrapy 1.7.3 started (bot: ppboard)
...
2019-10-01 15:37:53 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.ppomppu.co.kr/zboard/zboard.php?id=ppomppu4&category=3> (referer: None)
['[Amazon] Logitech G29 Gaming Racing Wheel ($183.01/무료)', '[aliexpress] 레노버 S340 15api 랩탑용 키보드 스킨 (1.79$ / Free)',
...
scrapy shell 에서 실행한 것과 같은 결과가 콘솔에서 잘 확인된다.
이제 콘솔 말고 파일로 저장하자.
Pipeline 사용
settings.py 파일에서 아래 항목을 활성화 해주면 기본적으로 생성되어 있는 pipeline 이 실행된다.
기본 코드 PpboardPipeline
아무것도 안한다. 구현을 해야 한다.
공식문서의 json 저장 예제인 JsonWriterPipeline
를 적용해 보자.
# ppboard/pipelines.py
import json
class PpboardPipeline(object):
def process_item(self, item, spider):
return item
class JsonWriterPipeline(object):
def open_spider(self, spider):
self.file = open('items.jl', 'w')
def close_spider(self, spider):
self.file.close()
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
pipeline 에서는 Item class 를 가지고 데이터를 처리한다.
settings.py 에 추가한다.
# ppboard/settings.py
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'ppboard.pipelines.PpboardPipeline': 300,
'ppboard.pipelines.JsonWriterPipeline': 400,
}
XXXPipeline() 을 여러개 만들어 위 settings.py 의 ITEM_PIPELINES 에 추가하여 실행시킬 수 있다.
300
숫자는 여러개의 pipeline 의 실행 우선순위이다.
이곳에서 spider 가 넘긴 데이터를 pipeline 내에서 정제, 가공하면 되겠다.
Feed exports
Feed exports 를 사용하면 Scrapy 가 지원하는 형식으로 쉽게 저장할 수 있다.
$ scrapy crawl ppb3 -o data.json
$ scrapy crawl ppb3 -o data.csv
$ scrapy crawl ppb3 -o data.xml
$ scrapy crawl ppb3 -s FEED_URI='export.csv' -s FEED_FORMAT=csv
$ scrapy crawl ppb3 -s FEED_URI='export.json' -s FEED_FORMAT=json
'python' 카테고리의 다른 글
tkinter와 cffi 간단한 툴 제작 (0) | 2024.04.11 |
---|---|
python2 기본 환경에서 python3 사용하려면 feat. AI (1) | 2024.03.12 |
Python: f-String (Literal String Interpolation) (0) | 2020.04.28 |
BeautifulSoup Document 정리 2 (0) | 2019.10.02 |
BeautifulSoup Document 정리 1 (0) | 2019.10.02 |