[Python] 스크래핑/크롤링

2020. 6. 26. 16:00

파이썬에서 웹을 요청할 수 있는 라이브러리
1- requests 라이브러리 (s붙음 주의) - 추가
2- urllib 라이브러리 - 내장모듈

차이점
1- requests는 요청 메소드(get/post)를 구분하지만 urllib는 보내는 데이타 여부에 따라 구분됨
2- 데이타 보낼 때 requests는 딕셔러니 형태로 urllib는 인코딩한 바이너리 형태로 보낸다

requests 라이브러리 추가
메뉴 > File > Settings > Project Interpreter > + 버튼 > 'requests' 검색 후 인스톨

 

터미널에서 (PyCharm을 사용하지 않는다면)
> pip install requests

install Package

[ requests 모듈 ]
(1) Rest API 지원
import requests
resp = requests.get('http://www.mywebsite.com/user')
resp = requests.post('http://www.mywebsite.com/user')
resp = requests.put('http://www.mywebsite.com/user/put')
resp = requests.delete('http://www.mywebsite.com/user/delete')

(2) 파라미터가 딕셔너리 인수로 가능
data = {'firstname':'John', 'lastname':'Kim', 'job':'baksu'}
resp = requests.post('http://www.mywebsite.com/user', data=userdata)

(3) json 디코더 내장 (따로 json 모듈 사용 안해도 됨)
resp.json()

 

requests로 사이트 읽기
import requests as rq
url = "http://www.google.com"
resp = rq.get(url)
print(resp)
print(resp.text)
print(resp.content)

헤더 가져오기

headers = resp.headers
for header in headers:
    print(header,">>",headers[header])

헤더는 딕셔너리 구조

urllib으로 읽기
from urllib import request  #주의 : request에 s에가 없음
site = request.urlopen(url)
page =site.read()
print(page)

requests에서 resp.content와 같음

print(site.status)
header = site.getheaders()
print(header)

status는 상태 200이면 성공

urllib의 header는 리스트에 튜플구조

for head in header:
    print(head[0],">>",head[1])

구글 로고 이미지 가져오기

urllib 라이브러리(패키지):
- URL를 다루는 모듈을 모아 놓은 패키지
- Http Ftp를 사용하여 데이터를 다운로드 할 때 사용하는 라이브러리

[] request 모듈 : 웹 요청을 보내고 받는 기능을 하는 모듈
- urlretrieve() 함수를 이용하여 이미지를 다운로드 받아 파일로 저장한다.

from urllib import request as req
url = "https://www.google.co.kr/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
imgName="data/google.png"
req.urlretrieve(url,imgName)

url open

# urlretrieve(): 파일로 바로 저장
# urlopen(): 파일로 바로 저장하기 않고 메모리에 로딩을 한다.

[참고] 파일저장 기본방식
f = open('a.txt','w')
f.write("테스트 내용")
f.close()

위의 과정을 with 문으로 간략하게 close 필요없음
with open("a.txt","w") as f:
f.write("테스트 내용")

 

from urllib import request
url = "https://t1.daumcdn.net/daumtop_chanel/op/20170315064553027.png"
imgName="data/daum.png"
site = request.urlopen(url)
downImage = site.read() #downImage는 어떤 객체(메모리)를 가리킴

with open(imgName,'wb') as f:#이미지 저장은 binary모드 b옵션 줘야함 default는 t(text)
    f.write(downImage)

 

urllib parse urljoin

urllib.parse.urljoin() : 상대경로를 절대경로로 변화하는 함수

from urllib.parse import  urljoin
baseUrl = "http://www.example.com/html/a.html" #가짜사이트
print(urljoin(baseUrl,'b.html'))
print(urljoin(baseUrl,'sub/c.html')) #끝 경로를 바꿔줌
print(urljoin(baseUrl,'/sub/c.html')) #절대경로로 입력하면 페이지도메인 다음에 바로 붙임
print(urljoin(baseUrl,'../sub/c.html'))
print(urljoin(baseUrl,'http://www.daum.net')) #새로운 url이 들어오면 바꿔줌

API

* API (Application Programming Interface)
: 어느 프로그램 기능을 외부 프로그램에서 사용할 수 있도록 만든 것
즉 서로 다른 프로그램이 기능을 공유할 수 있도록 한 것


** Web API
: 웹상의 많은 정보를 공유할 수 있도록 제공하는 것
단점은 해당 제공자의 사정에 의해 변동이 심하다.

` 다음 개발자 센터
` 네이버 개발자 센터
` 구글 개발자 센터
` [그외] https://www.apistore.co.kr/api/apiList.do

 

http://www.data.go.kr
- 회원가입필수
- 일반인증키 요청 ( 바로 받을 수 있고 자료요청시 바로 승인됨 사용까지 1시간 소요)

> 관광자원통계서비스 > 상세기능 > 유료관광지방문객수조회
: 전국의 주요 유로관광지 방문객수를 조회하기 위한 서비스로서
기간,지역, 관광지별 외국인 방문객수와 내국인 방문객수를 조회한다.

의미있는 데이타를 추출하여 출력한다

 

 

beautifulsoup4

from bs4 import BeautifulSoup

html = """
    <html><body>
        <h1>스크레이핑 연습</h1>
        <p>웹페이지 분석하자</p>
        <p>데이타 정제하기</p>
    </body></html>
"""

# 1. 데이타 파서하기 메모리 구조처럼 올린다.
soup = BeautifulSoup(html,'html.parser')
# 2. 원하는 요소 접근하기
h1 = soup.html.body.h1
# 3. 요소의 내용 추출하기
print(h1)

 

print(h1.text)

print(soup.html.body.p)
print(soup.html.body.p.text)
p = soup.find_all("p")
print(p)

여러개 찾으려면 find_all로 리스트로 만든 후 리스트에서 뽑기

for i in p:
    print(i.text)

속성 값 가져오기
from bs4 import BeautifulSoup

html = """
    <html>
        <body>
            <ul>
                <li><a href='http://www.naver.com'>네이브</a></li>
                <li><a href='http://www.daum.net'>다아음</a></li>
            </ul>
        </body>
    </html>
"""

# 리스트의 내용과 해당 경로를 추출하기
soup = BeautifulSoup(html,"html.parser")
links=soup.find_all('a')
for a in links:
    print(a.attrs['href'])

이미지 경로를 찾고 그 경로를 urlretrieve() 를 사용하면 바로 저장할 수 있다.

beautifulsoup은 id와 class로 찾을 수 있다.

 

id와 class로 찾기
from bs4 import BeautifulSoup

html = """
    <html><body>
        <div id='course'>
            <h1>빅데이터 과정</h1>
        </div>
        <div id='subjects'> 
            <ul class='subs'>
                <li>머신러닝</li>
                <li>데이터 처리</li>
                <li>데이타 분석</li>
            </ul>
        </div>
    </body></html>
"""
soup = BeautifulSoup(html,"html.parser")
# (1) id값으로 찾기
h1=soup.select_one('#course > h1')#아이디는 하나기에 select_one
print(h1.text)
print(h1.string)
# (2) class값으로 찾기
lis = soup.select('.subs > li')
for li in lis:
    print(li.text)
    print(li.string)

** css js selector와 비슷하게 찾을 수 있다.

select_one 하나만 찾는다.

select 여러개를 찾아 리스트로 만든다.

 

Naver에서 미국USD 값 가져오기

from bs4 import BeautifulSoup
from urllib import request as req


# 웹 문서 가져오기
url = 'https://finance.naver.com/marketindex/'
res = req.urlopen(url)
soup = BeautifulSoup(res,'html.parser')
print(soup.select_one("#exchangeList .point_dn .value").text)

교보문고 크롤링하기

https://search.kyobobook.co.kr/web/search?vPstrKeyWord=python

 

python 검색 - 인터넷교보문고

27,000원 [10%↓] 1,500원P

search.kyobobook.co.kr

교보문고에서 파이썬 책 검색하여
- csv 파일로 저장
- mysql 테이블에 저장

 

from urllib.request import urlopen
from urllib.request import urlretrieve
from bs4 import BeautifulSoup
import re

# 교보문고 > '파이썬' 검색 > 국내도서
html = urlopen("https://search.kyobobook.co.kr/web/search?vPstrKeyWord=python")
#BeautifulSoup 이용 책의 제목을들 추출하여 출력
#총 책의 권수를 출력
soup=BeautifulSoup(html,"html.parser")
titles = soup.select("td.detail div.title strong")
print(titles)
strt = "안녕"
bookName = []
for title in titles:
    name = title.text
    print("책 이름 :",name)
    name = name.strip()
    # name = re.sub("[^A-Za-z0-9ㄱ-힣]","_",name)
    name = name.replace("/","_")
    bookName.append(name)
print("책의 권 수 :",len(titles))
print(bookName)
images = soup.select("td.image div.cover > a >img")
for idx,image in enumerate(images):
    fileName="./data/bookimg_{0}.jpg".format(bookName[idx])
    urlretrieve(image.attrs['src'],fileName)

셀레니움

selenium
- 주로 웹앱을 테스트하는데 이용하는 프레임워크
- 웹 브라우저를 원격으로 조작할 때 사용
- 자동으로 URL을 열고 클릭, 스크롤, 문자 입력등의 동작을 조작할 수 있다.
- webdriver라는 API를 통해 운영체제에 설치된 Chrome등의 브라우저를 제어하게 된다.

[설치] 메뉴 > File > Settings > Project Interpreter > + 버튼
selenium 검색 후 인스톨
> pip install selenium

[참고] Selenium의 버전은 자주 업데이트 되고, 브라우저의 업데이트 마다 새로운 Driver를 잡아주기 때문에
항상 최신버전을 깔아 주는 것이 좋다.

[매뉴얼]
` https://selenium-python.readthedocs.io/index.html
` https://docs.seleniumhq.org/docs/

셀레니움 모듈 다운

크롬 웹드라이버 ( Chrome WebDriver )

[다운로드] http://chromedriver.chromium.org/downloads
chromedirver_win32.zip 파일 다운로드 받고 압축풀기
2019.07.24 - ChromeDriver 75.0.3770.140 ( 반드시 이 버전만 되었다

크롬 버전과 맞춰야 함

Selenium은 driver객체를 통해 여러가지 메소드를 제공한다.
  - HTML을 브라우저에서 파싱해주기 때문에 굳이 Python와 BeautifulSoup을 사용하지 않아도 된다.


[ URL에 접근하는 api ]

get(‘http://url.com’)


1. DOM 내부에 있는 여러 요소 중 첫 번째 요소(element) 찾는다.

find_element_by_name(‘HTML_name’)
find_element_by_id(‘HTML_id’)
find_element_by_css_selector(‘#css > div.selector’)
find_element_by_class_name(‘some_class_name’)
find_element_by_tag_name(‘h1’)
find_element_by_xpath(‘/html/body/some/xpath’) : xpath 지정하여 해당 요소 추출
find_element_by_link_text(‘text’) : 링크 텍스트로 요소 추출

2. DOM에서 모든 요소 추출
find_elemens_by_css_selector(‘#css > div.selector’)
find_elements_by_class_name(‘some_class_name’)
find_elements_by_tag_name(‘h1’)

3. DOM 요소에 적용할 수 있는 메소드와 속성
clear()             : 글자를 지움
click()             : 클릭
get_attribute(name) : 요소의 속성 name에 해당하는 값을 추출
is_displayed()      : 요소가 화면에 출력되는지 확인
is_enabled()
is_selected()
save_screenshot(filename)
submit()

외에도 많은 속성과 메소드가 있습니다.

또한 각 브라우저 드라이버 객체의 속성도 있음

웹사이트 화면 캡쳐

from selenium import webdriver
# 1. webdriver 객체생성
driver = webdriver.Chrome("./webdriver/chromedriver.exe") #드라이버 설정 다운받은 크롬드라이버 경로
driver.implicitly_wait(2) #2초를 쉰다. (접속하는 시간을 생각)
# 2. 페이지 접근
driver.get('https://www.naver.com')
# 3. 화면을 캡처해서 저장하기
driver.save_screenshot("Website.png")

구글 검색

from selenium import webdriver
# 1. webdriver 객체생성
driver = webdriver.Chrome("./webdriver/chromedriver.exe") #드라이버 설정 다운받은 크롬드라이버 경로
driver.implicitly_wait(2) #2초를 쉰다. (접속하는 시간을 생각)
# 2. 페이지 접근
# driver.get('https://www.naver.com')
driver.get("https://www.google.com")
#----------------------------------------------
# [2]
search_bt=driver.find_element_by_name('q')
search_bt.send_keys("코로나극복")
search_bt.submit()

굽네 매장 정보 가져오기
from selenium import webdriver
from bs4 import BeautifulSoup
import time
#-------------------------------1. 웹 페이지 접근
# 웹드라이버 객체 생성
driver = webdriver.Chrome('./webdriver/chromedriver')
driver.implicitly_wait(3)

# 페이지 접근
driver.get('http://www.goobne.co.kr/store/search_store.jsp')
for i in range(1,106):
    driver.execute_script("store.getList('"+str(i)+"')")
    time.sleep(3)
    html = driver.page_source
    soup = BeautifulSoup(html,'html.parser')
    for store_list in soup.find_all("tbody",attrs={"id":"store_list"}):

        for name,tel,addr in zip(soup.select('tr > td:first-child'),soup.select('.store_phone > a'),soup.select(".t_left > a")):
            print(name.text,tel.string,addr.string)

BELATED ARTICLES

more