Web Scraper in 30 Minutes 강철 <kang@cheol.net>
발표자 소개 KAIST 전산학과 2015년부터 G사에서 일합니다. 에서 대한민국 정치의 모든 것을 개발하고 있습니다.
목표 웹 스크래퍼를 프레임웍 없이 처음부터 작성해 본다.
목표 웹 스크래퍼를 프레임웍 없이 처음부터 작성해 본다. 스크래퍼/크롤러의 작동 원리를 이해한다.
목표 웹 스크래퍼를 프레임웍 없이 처음부터 작성해 본다. 스크래퍼/크롤러의 작동 원리를 이해한다. 언제든 필요할 때 동시성 크롤러를 직접 구현
목차 개론 스크래퍼(Scraper), 크롤러(Crawler) 웹(WWW)의 동작 방식 실습 1. 2. 3. 4. Chrome Developer Tools로 웹사이트 구조 파악하기 Requests로 웹페이지 요청하기 scrapy.selector를 이용해 데이터 추출하기 gevent로 여러 페이지 동시에 요청하기
Scraper, Crawler Web crawling: 웹에서 링크를 타고다니며 웹페이지들을 수집하는 행위 예) Google bot이 전 세계의 웹사이트를 수집하여 검색 서비스 제공 Web scraping: 웹사이트에서 정보를 추출하는 행위 예) 쇼핑몰 가격비교 - 각 쇼핑몰 상품 페이지에서 상품 이름, 가격 등을 추출
Scraper, Crawler Google 검색 결과 (structurized)
왜 필요한가 국회 의안정보시스템.
왜 필요한가 1. 의원 이름을 클릭하면 그 의원의 다른 법안들도 볼 수 있음 좋겠는데 2. 이 의원의 출석률은 얼마나 될까? 3. 이 법안을 발의한 의원들의 정당 분포가 어떻게 될까? 전부 새누리당? 아니면 반반? 제공되는 기능 외에 하고 싶은 게 너무 많아!
왜 필요한가 국회, 선거관리위원회 등 국가 정보시스템 데이터를 수집해 만든 대한민국 정치의 모든 것 (http://pokr.kr/)
웹(WWW)의 동작 방식 server client 이미지 출처: wikipedia.
웹(WWW)의 동작 방식 1. Request - url - header - data 이미지 출처: wikipedia.
웹(WWW)의 동작 방식 1. Request - url - header - data 2. HTML, resources - image - css - JavaScript 이미지 출처: wikipedia.
웹(WWW)의 동작 방식 3. 브라우저는 그걸 받아 렌더링 1. Request - url - header - data 2. HTML, resources - image - css - JavaScript 이미지 출처: wikipedia.
실습: TED.com 스크래핑하기
실습: TED.com 스크래핑하기 목표: 최신 비디오 목록을 긁어모아 json으로 저장한다.
1. Chrome Developer Tools로 웹사이트 구조 파악하기 Request URL, method, parameter 등을 확인한다.
2. Requests 이용해 HTML 다운로드 import requests def fetch_page(url): r = requests.get(url) return r.text with open( sample.html, w ) as f: html = fetch_page( http://www.ted.com/talks/browse?page=2 ) f.write(html.encode( utf-8 ))
2. Requests 이용해 HTML 다운로드 sample.html sample.html
3. DOM 구조 파악하기
4. 목록에서 게시물 링크들 추출하기 from urlparse import urljoin from scrapy.selector import Selector # 실행결과 [u'http://www.ted.com/talks/jamila_lyiscott_3_ways_to_speak_english', u'http://www.ted.com/talks/ruth_chang_how_to_make_hard_choices', u'http://www.ted.com/talks/anne_curzan_what_makes_a_word_real', ] def talk_links_from_listpage(url): html = fetch_page(url) sel = Selector(text=html) talk_links = sel.css('.talk-link.media message a::attr(href)').extract() talk_links = [urljoin(url, talk_link) for talk_link in talk_links] return talk_links from pprint import pprint pprint(talk_links_from_listpage( http://www.ted.com/talks/browse?page=2 ))
5. 각 게시물 세부정보 요청하기 import re def latest_talks(page=1): list_url = 'http://www.ted.com/talks/browse?page={0}'.format(page) download_re = re.compile(r'http://download.ted.com/talks/[^"]+') def talk_from_page(url): html = fetch_page(url) talk_links = talk_links_from_listpage(list_url) talks = [talk_from_page(url) for url in talk_links] return talks sel = Selector(text=html) download_m = download_re.search(html) return { 'title': sel.css('.talk-hero title::text').extract(), 'description': sel.css('.talk-description::text').extract(), 'download': download_m.group(0) if download_m else None, } pprint(latest_talks())
6. 동시에 여러 페이지 요청하기 from gevent import monkey; monkey.patch_all() from gevent.pool import Pool def latest_talks(page=1): list_url = 'http://www.ted.com/talks/browse?page={0}'.format(page) talk_links = talk_links_from_listpage(list_url) # talks = [talk_from_page(url) for url in talk_links] pool = Pool(20) # XXX: constant talks = pool.map(talk_from_page, talk_links) return talks pprint(latest_talks()) # 단 5줄 변경만으로: 34초 8초
정리 Python의 쉽고 간결한 문법과 강력한 라이브러리를 이용하면 간단한 스크래퍼 정도는 30분이면 충분히 짜고 남는다.
Q&A
Scrapy 좋아요 command line tools referer & user-agent item pipeline export to file/db crawling: link extraction, queueing, scheduling retry & failover logging daemonize distributed execution
감사합니다