Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기

Beomi
August 15, 2017

PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기

파이콘 KR 2017 튜토리얼 <나만의 웹 크롤러 만들기> 세션 자료입니다.

Beomi

August 15, 2017
Tweet

More Decks by Beomi

Other Decks in Technology

Transcript

  1. PYCON KR 2017 튜토리얼 < 나만의 웹 크롤러 만들기> 이준범

    ([email protected]) PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 1
  2. 오늘 할것 1. HTML DOM 구조 익히기 & CSS Selector

    2. 크롬 사용법 알기 3. Request & BeautifulSoup4 사용법 익히고 간단한 크롤러만들기 4. Selenium 사용법 익히기 5. Selenium -> Requests: 어려운건 Selenium, 쉬운건 Requests! 6. 서버에 올려봅시다 7. 텔레그램 봇 만들기 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 4
  3. HTML DOM = HTML Element 로 구성된 Tree <!DOCTYPE html>

    <html> <head> <title> 타이틀</title> </head> <body> <h1> 제일 큰 제목</h1> <div> 파이콘 2017 KR </div> </body> </html> PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 7
  4. 파이콘 2017 KR = html > body > div >

    는 앞선 element 의 자식( child ) PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 8
  5. < 실습 > 파이콘 사이트 구조, 까봅시다 PYCON KR 2017

    튜토리얼: 나만의 웹 크롤러 만들기 9
  6. 사람이 읽을 수 있는( 쓸 수 있는) 쉬운 HTTP 요청

    PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 13
  7. HTML 가져오기: .text # 01_pycon.py import requests # GET 방식으로

    pycon 홈페이지 가져오기 response = requests.get('https://www.pycon.kr/2017/') # 가져온 response 의 HTML가져오기 print(response.text) # 소스보기랑 같아요 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 16
  8. <!DOCTYPE html> <html> <head> <title> 파이콘 한국 2017</title> <meta charset="utf-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=0.85"> <!-- Opengraph tag --> <meta property="og:site_name" content=" 파이콘 한국 2017"> <meta property="og:title" content=" 파이콘 한국 2017"> <meta property="og:image" content="https://www.pycon.kr/2017/static/image/pyconkr-20 <meta property="og:url" content="https://www.pycon.kr/2017/"> <meta property="og:description" content=" 파이콘 한국 2017"> <!-- Include basic items --> <link href="/2017/static/components/bootstrap/dist/css/bootstrap.min.css" rel <link href="/2017/static/components/bootstrap-social/bootstrap-social.css" rel <link href="/2017/static/components/font-awesome/css/font-awesome.min.css" rel <link href="/2017/static/components/montserrat-webfont/css/montserrat-webfont.min.cs PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 17
  9. # 02_pycon_bs4.py import requests from bs4 import BeautifulSoup as bs

    response = requests.get('https://www.pycon.kr/2017/') html = response.text # HTML # 파이썬이 이해하는 구조로 조각조각 잘라주기 # 자르는 가위의 이름은 'html' 패키지의 'parser' 모듈 soup = bs(html, 'html.parser') html.parser 대신 lxml 이라는 좋은 패키지도 있습니다.( 추가설치 필요) pip install lxml # 설치하기 soup = bs(html, 'lxml') # html.parser 대신 lxml PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 21
  10. # 02_pycon_bs4.py import requests from bs4 import BeautifulSoup as bs

    response = requests.get('https://www.pycon.kr/2017/') html = response.text soup = bs(html, 'html.parser') # CSS Selector 로 원하는 부분 가져오기 soup.select('CSS Selector 를 여기에 넣어줍시다') CSS Selector? PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 22
  11. CSS Selector id 는 # 으로, 한 HTML 안에는 한개의

    id class 는 . 으로, 한 HTML 에 비슷한(같은) 요소들은 같은 class DOM Tree 는 > 으로, 부모 자식관계! 특정한 태그만 가져오려면 태그이름만! 더 많은 내용은 이곳으로 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 23
  12. 조금더, CSS Selector soup.select('a[href]') # a 태그 중 href 속성을

    가진 elements 리스트(list) 를 반환 [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 24
  13. # a 태그 중 링크가 http://example.com/elsie 인 Elements soup.select('a[href="http://example.com/elsie"]') #

    [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>] # a 태그 중 링크가 http://example.com/ 으로 시작하는(^) Elements soup.select('a[href^="http://example.com/"]') # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] # a 태그 중 링크가 tillie 로 끝나는($) Elements soup.select('a[href$="tillie"]') # [<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>] # a 태그 중 링크가 .com/el 이 들어가있는 Elements soup.select('a[href*=".com/el"]') # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>] PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 25
  14. 파이콘 제목 가져오기 # 02_pycon_bs4.py import requests from bs4 import

    BeautifulSoup as bs response = requests.get('https://www.pycon.kr/2017/') html = response.text soup = bs(html, 'html.parser') # CSS Selector 로 원하는 부분 가져오기( 리스트) title = soup.select('body > div.frontpage > div.onsky > div > div > h1') # 리스트에서 첫번째 Element 에서 html 태그 뺀 텍스트 가져오기 print(title[0].text) PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 27
  15. 만들어보세요: 파이콘 일정 & 장소 가져오기 https://www.pycon.kr/2017/ 잠깐! nth-child 는

    쓰지 못하니 CSS Selector 에서 지워주세요! PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 28
  16. # 03_pycon_bs4_test.py import requests from bs4 import BeautifulSoup as bs

    response = requests.get('https://www.pycon.kr/2017/') html = response.text soup = bs(html, 'html.parser') content_list = soup.select('body > div.frontpage > div.onsky > div > div > p > span' for i in content_list: print(i.text) PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 29
  17. # 04_pycon_speakers.py import requests from bs4 import BeautifulSoup as bs

    response = requests.get('https://www.pycon.kr/2017/program/speaker/') html = response.text soup = bs(html, 'html.parser') content_list = soup.select('div.col-md-9.content > ul > li > div > h4 > a') for i in content_list: print(i.text) PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 31
  18. a 태그의 링크도 가져올수 있어요 # 05_pycon_speakers_link.py import requests from

    bs4 import BeautifulSoup as bs response = requests.get('https://www.pycon.kr/2017/program/speaker/') html = response.text soup = bs(html, 'html.parser') content_list = soup.select('div.col-md-9.content > ul > li > div > h4 > a') for i in content_list: print(i['href'])) # a 태그의 'href' 속성을 가져옵시다 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 33
  19. GET QueryString 붙이기 쿼리스트링은 url 끝에 ? 인자이름=값& 인자이름2=값 와

    같은 형태 requets 에서는 params 로 넘겨줄 수 있다 requests.get('http://onoffmix.com/event') # != requests.get('http://onoffmix.com/event?s= 파이썬') # == requerts.get('http://onoffmix.com/event', params={'s':' 파이썬'}) ? 뒤에 바로 값을 전달해도 되고 params 로 값을 전달해도 됩니다 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 35
  20. HTTP 는 매번 요청시마다 HTTP 전달 후 요청을 끊는다 그러면

    로그인은? PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 38
  21. 로그인을 하면 로그인 정보가 쿠키와 세션에 담긴다 => 요청시마다 함께

    전송하면 서버는 내가 누구인지 알 수 있다! PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 40
  22. 로그인 폼은 form 태그로 만들어집니다 form 태그 안에는 input 태그들

    input 태그 속성에는 name 속성이 있다. form 전송시에는 { name 속성이름 : 사용자입력값 } 의 형태로 전송 ' 전송' 하는 것은 POST 방식 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 42
  23. requests.Session() 이용해 로그인상태 유지하기 | data 에 넣어주기 import requests

    from bs4 import BeautifulSoup as bs # 세션 만들기( 로그인정보 유지) s = requests.Session() # 크롬 브라우저라고 서버에 알려주기 s.headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)' 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36' } # `post` 방식으로 로그인하기 # email / pw / proc 는 input 태그의 name 속성값 login = s.post('https://onoffmix.com/account/login', data={ 'email': ' 이메일', 'pw': ' 패스워드', 'proc': 'login' }) PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 43
  24. # 위 코드 이어서 # 로그인 된 상태로 신청 이벤트

    페이지 가져오기 html = s.get('http://onoffmix.com/account/event') soup = bs(html.text, 'html.parser') # 신청 이벤트 목록 만들기 event_list = soup.select('#eventListHolder > div > ul > li.title > a') for event in event_list: print(event.text) PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 45
  25. 브라우저를 쓰고싶어! Selenium! pip install selenium https://sites.google.com/a/chromium.org/chromedriver/downloads 여러분의 크롬은 60

    버전인가요? chrome://chrome 에서 확인해 보세요 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 47
  26. from selenium import webdriver driver = webdriver.Chrome('/Users/ 사용자이름/Downloads/chromedriver') # Selenium

    이 모든 자원을 가져오기까지 3 초를 기다려줍니다 driver.implicitly_wait(3) # 네이버 첫 화면을 가져와봅시다 driver.get('https://naver.com') webdriver 를 통해 실 브라우저를 띄우고 조작할 수 있습니다 webdriver.Chrome 안의 첫번째 인자는 앞서 받은 chromedriver 의 정확한위치를 넣어줘야 합니다. implicit_wait 을 통해 웹 페이지가 로드될때까지 암묵적으로 기다려줍니다. 이렇게 기다려주는 것은 웹 페이지 자체를 기다리거나 혹은 특정 요소(element) 를 기다려 줄수도 있습니다. PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 49
  27. 요소찾기: find_element_by_css_selector driver 를 통해 많은 방법으로 찾을 수 있지만,

    여전히 CSS Selector 는 편리 input_id = driver.find_element_by_css_selector('#id') input_pw = driver.find_element_by_css_selector('#pw') login_button = driver.find_element_by_css_selector( '#frmNIDLogin > fieldset > span > input[type="submit"]' ) 새로운 Selector : input[type="submit"] input 태그 중 type Attribute 의 값이 "submit" 인 Element 여러개 요소는 find_elements_by_css_selector ( element -> elements ) PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 50
  28. 네이버카페는 iframe 을 사용합니다 Javascript 로 iframe 을 끼워넣기 합니다

    프레임 내부 url 을 까봐야 합니다 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 53
  29. 네이버카페 중고나라 노트북/ 맥북/ 넷북의 경우 화면에 보이는 url: http://cafe.naver.com/joonggonara

    실제 프레임 url: http://cafe.naver.com/joonggonara? iframe_url=/ArticleList.nhn%3Fsearch.clubid=10050146%26search. menuid=334%26search.boardtype=L PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 54
  30. from selenium import webdriver import time driver = webdriver.Chrome('chromedriver') driver.implicitly_wait(3)

    driver.get('https://naver.com') input_id = driver.find_element_by_css_selector('#id') input_pw = driver.find_element_by_css_selector('#pw') login_button = driver.find_element_by_css_selector( '#frmNIDLogin > fieldset > span > input[type="submit"]' ) input_id.send_keys('') input_pw.send_keys('') login_button.click() PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 55
  31. 네이버는 iframe 을 사용하기 때문에 외부와 내부가 불러지는 시간이 다름

    iframe 으로 driver 위치를 전환시켜줘야 find~ 를 사용가능함 # 이어서... url = 'http://cafe.naver.com/joonggonara?iframe_url=/ArticleList.nhn%3Fsearch.clubid=1 driver.get(url) time.sleep(3) driver.switch_to_frame('cafe_main') selector = '#main-area > div:nth-child(8) > form > table > tbody > tr > td.board-list contents = driver.find_elements_by_css_selector(selector) for post in contents: print(post.text) driver.quit() PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 56
  32. # 09_naver_cafe_headless.py from selenium import webdriver import time options =

    webdriver.ChromeOptions() options.add_argument('headless') options.add_argument('window-size=1920x1080') driver = webdriver.Chrome('chromedriver', chrome_options=options) driver.implicitly_wait(3) driver.get('https://nid.naver.com/nidlogin.login') # 로그인만 하는 주소 # ... 이하 동일 PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 58
  33. 우분투 16.04 LTS Tokyo 서버 제일 싼거..(2.5 달러나 5 달러)

    PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 61
  34. Python 기본을 설치해줍시다 apt-get update && apt-get upgrade -y apt-get

    install build-essential apt-get install python3 python3-pip pip3 install setuptools Locale 설정을 해줍시다 (locale.Error 방지용) apt-get install language-pack-ko locale-gen ko_KR.UTF-8 update-locale LANG=ko_KR.UTF-8 LC_MESSAGES=POSIX PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 62
  35. 크롬을 깔아봅시다 vi /etc/apt/sources.list 로 파일을 엽니다 i 키를 누르면

    수정이 됩니다. 파일 끝으로 내려가서 deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main 를 추가해 주세요.( 한줄 추가) esc 를 누르고 ZZ 엔터로 나올 수 있습니다. wget https://dl.google.com/linux/linux_signing_key.pub sudo apt-key add linux_signing_key.pub apt-get update apt-get install google-chrome-stable PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 63
  36. 크롬 driver 를 받아줍시다 wget \ https://chromedriver.storage.googleapis.com/2.31/chromedriver_linux64.zip apt-get install unzip

    unzip chromedriver_linux64.zip 위와 같이 하시면 /root/chromedriver 에 크롬 드라이버가 위치합니다. PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 64
  37. Crontab -e # 매분마다 * * * * * /usr/bin/python3

    /root/crawler.py # 10 분마다 */10 * * * * /usr/bin/python3 /root/crawler.py # 매시 0 분마다 0 * * * * /usr/bin/python3 /root/crawler.py PYCON KR 2017 튜토리얼: 나만의 웹 크롤러 만들기 66