[ 오늘 배운 내용 ]
1. G마켓 이미지 데이터 수집 실습
2. 셀레니움(Selenium)
- 간단한 머신러닝 실습
- TED talks 영상들의 한국어 제목 데이터 수집
- Headless하게 셀레니움 사용하기
3. 네이버 중고나라 게시글 데이터 수집 (iframe태그)
4. xpath
- 네이버 연관검색어 수집 (scrapy프레임워크 사용)
5. iterator와 generator (yield 사용)
6. scrapy 프레임워크
- G마켓 베스트셀러 상품 데이터 수집
동적페이지와 정적페이지의 차이에 대해서는 강사님께서 매일 몇번씩 설명해주셨기 때문에 완벽하게 이해가 된 것 같다. 데이터 크롤링에 있어서 상당히 중요한 개념이라는 생각이 들었다.
먼저 G마켓의 상품 데이터가 들어있는 csv파일을 불러와서 안의 이미지 url을 사용해서 확인하는 실습을 해보았다. 이미지를 보고싶으면 파이썬의 pillow 패키지를 사용하면 된다.
다음으로 셀레니움(Selenium)을 사용하는 실습을 했다.
셀레니움을 사용하는 크롤링은 느리기 때문에 좋은 크롤링 방법이라고 하긴 어렵지만 정기적으로 데이터를 크롤링 해야 하는 경우 이런 자동화 툴을 사용할 줄 알아야 하기 때문에 알고는 있어야 한다.
코드를 작성해서 크롬 브라우저를 열고, 사이트를 이동하고, 검색어를 입력하고, 다시 브라우저를 닫는 것을 해보니 신기했다.
간단하게 셀레니움 사용법만 익히고 시간이 애매해서 단 2줄의 코드로 머신러닝을 돌리는 것을 강사님이 보여주셨다. 사실 인공지능 모델 같은건 대부분 이미 있는 것을 갖고와 사용하기 때문에 가장 시간이 많이 들고 어려운 부분은 데이터 전처리라고 한다.
간단한 머신러닝을 해본 뒤 셀레니움으로 진짜 TED 사이트에 가서 영상 제목 데이터를 수집해보았다. 이것 말고도 Headless하게 브라우저를 실행하여 크롤링 하는 실습도 해봤는데 이는 서버 컴퓨터 등과 같이 브라우저를 화면에 띄울 수 없는 환경에서 필요한 기능인 것 같다.
다음으로 네이버 중고나라 게시글 데이터를 수집했는데 다른 실습과 다른 점은 중고나라 게시물들이 iframe 태그 안에 들어 있기 때문에 브라우저 드라이버의 프레임을 이동시켜주어야 했다는 것이다.
마지막으로 수업했던 내용들은 많이 어려웠다. 수업을 들어도 잘 이해가 가지 않았고, 강사님께서도 현업에서는 많이 쓰는 방법이니 이런게 있구나 하고 알기만 하라고 하셨다.
html에서 엘리먼트를 선택하는 방법으로 css 선택자 말고도 xpath라는 방법이 있는데 이는 scrapy라는 프레임워크에서 사용하는 선택자라고 한다.
css 선택자와 조금 다른 xpath의 문법을 배워보았고 scrapy 프로젝트를 만들어서 G마켓 상품 데이터를 수집해보았다. 처음 들어보는 용어도 많고 당장 쓸 일은 많이 없을 것 같아 이번 웹크롤링 수업에서는 앞부분에서 배웠던 동적페이지 크롤링과 BeautifulSoup를 사용한 정적페이지 크롤링을 기억하는 것이 우선일 것 같다.
[ 동적페이지와 정적페이지에서의 데이터 크롤링 차이 ]
- 동적페이지 : URL 변경 없이 웹 페이지 데이터 수정 (데이터를 JSON 포맷으로 서버에서 받아옴) --> 주로 API 사용할 때
- 정적페이지 : URL 변경 해서 웹 페이지 데이터 수정 (데이터를 HTML 포맷으로 서버에서 받아옴) --> css selector를 사용하여 원하는 데이터를 수집
1. G마켓 이미지 데이터 수집 실습
G마켓 상품들의 데이터가 있는 csv 파일을 데이터프레임으로 불러온 다음,
img 칼럼의 링크 데이터들을 돌면서 지정된 형식의 이름의 파일로 로컬에 저장하였다.
for idx, data in df[:5].iterrows():
filename = '0' * (3 - len(str(idx))) + str(idx) + '.png' # 파일 이름들을 같은 자릿수로 맞춰주어야 검색 시 순서대로 됨
print(idx, filename, data['img'])
response = requests.get(data['img'])
with open(f'{path}/{filename}', 'wb') as file:
file.write(response.content)
.iterrows() 를 사용하여 데이터프레임의 한 row씩 차례로 인덱스와 값을 받아왔다.
파일을 저장할 이름들을 같은 자릿수로 맞춰주기 위해 별도의 식을 넣어주었고, 파일을 생성한 뒤 url로 받아온 이미지 데이터를 생성한 파일에 write 해주었다.
파이썬의 이미지 데이터 전처리 패키지인 pillow를 사용하여 받은 이미지를 확인해보았다.
from PIL import Image as pil
pil.open(f'{path}/004.png')
실행결과
2. 셀레니움(Selenium)
- 브라우저의 자동화 목적으로 만들어진 다양한 브라우저와 언어를 지원하는 라이브러리
- 브라우저를 파이썬 코드로 컨트롤 해서 브라우저에 있는 데이터를 수집
==> 원래는 만들어진 코드의 기능들의 테스트를 자동화하기 위해 만들어졌는데 데이터 크롤링에도 많이 쓰이게 됐다.
[ 웹 페이지에서 데이터를 크롤링 하는 방법 ]
- 웹페이지의 API 트래픽을 분석해서 데이터 수집 : requests 패키지 (JSON포맷 데이터)
- 공식적으로 제공하는 API를 application key 받아서 데이터 수집 : requests 패키지 (JSON포맷 데이터)
- 웹페이지의 html 코드 받아서 데이터 수집 : requests 패키지, BeautifulSoup(css selector) (HTML포맷 데이터)
- 브라우저를 파이썬 코드로 컨트롤 해서 데이터 수집 : selenium ==> browser - python
크롤링할 때 좋은 순서는
2 > 1 > 3 > 4 이다
셀레니움은 1, 2, 3번 방법을 사용할 수 없을 때 사용하자
[ 셀레니움 환경설정 ]
셀레니움을 사용하려면 사용하려는 브라우저의 브라우저 드라이버를 다운 받아야 한다.
수업에서는 크롬 브라우저를 사용하였고, 크롬 브라우저와 같은 버전(메이저 버전만 맞춰주면 된다.)의 드라이버를 다운 받아야 한다. 드라이버는 브라우저와 파이썬 코드를 연결해주는 역할을 한다.
# 셀레니움 설치
!pip install selenium
# 임포트
from selenium import webdriver
from selenium.webdriver.common.by import By
# 1. 브라우저 띄우기
driver = webdriver.Chrome() # 크롬 드라이버가 같은 경로에 있거나 환경변수 설정이 돼있지 않으면 경로 지정 필요
# 2. 다음으로 페이지 이동
driver.get("https://daum.net")
# 3. 브라우저 사이즈 조절
driver.set_window_size(200, 600)
# 4. 브라우저 스크롤 조절(자바스크립트 코드 실행)
driver.execute_script('window.scrollTo(200,300);')
# 5. alert창 띄우기
driver.execute_script("alert('hello selenium!');")
# 6. alert창 닫기
alert = driver.switch_to.alert
alert.accept()
# 7. 스크롤 돌아오기
driver.execute_script("window.scrollTo(0,0);")
# 8. input 창에 "파이썬" 입력
driver.find_element(By.CSS_SELECTOR, '#q').send_keys("파이썬")
# 9. 검색 버튼 클릭 .c1.c2 -> c1클래스와c2클래스 둘 다 있는 엘리먼트
driver.find_element(By.CSS_SELECTOR, '.inner_search > .ico_pctop.btn_search').click()
# 10. 브라우저 종료
driver.quit()
브라우저를 띄우는 것은 메모리를 사용하기 때문에 작업이 끝난 브라우저는 quit()로 종료해준다.
[ 간단한 머신러닝 실습 ]
예전 시즌의 프리미어리그 20팀들의 득점/실점/승점 csv 데이터를 불러와서 간단한 머신러닝 찍먹을 해보았다.
머신러닝에 사용된 코드는 단 2줄이라 신기했다.
득점과, 실점을 입력하면 승점을 예측하는 간단한 프로그램이다.
# 프리미어리그 데이터 불러오기
df = pd.read_csv('premierleague.csv')
df.head()
# name gf ga points
# 0 Manchester City 106 27 100
# 1 Manchester United 68 28 81
# 2 Tottenham Hotspur 74 36 77
# 3 Liverpool 84 38 75
# 4 Chelsea 62 38 70
# feature와 target 설정
feature = df[["gf", "ga"]]
target = df["points"]
# 사이킷런 설치
!pip install sklearn
# 인공지능 모델 생성
from sklearn.linear_model import LinearRegression
model = LinearRegression().fit(feature, target)
# 데이터 예측 : 득점 80, 실점 36
np.round(model.predict([[80, 36]]))
# array([79.])
토트넘이 80골을 넣었어도 승점이 약 79 정도로 순위가 바뀌지 않았을 것이다 ㅋ
- 학습시킨 모델 저장
import pickle
# ram > ssd로 저장
with open("model.pkl", "wb") as file:
pickle.dump(model, file)
# ssd > ram으로 갖고오기
with open("model.pkl", "rb") as file:
load_model = pickle.load(file)
# 갖고온 모델 사용
np.round(load_model.predict([[80, 36]]))
# array([79.])
[ TED talks 영상들의 한국어 제목 데이터 수집 ]
# 브라우저 열기
driver = webdriver.Chrome()
# 페이지 이동
driver.get("https://ted.com/talks")
# select box에서 한국어 메뉴 클릭
driver.find_element(By.CSS_SELECTOR, '#languages [lang="ko"]').click()
# 전체 데이터의 제목과 링크 데이터 수집
elements = driver.find_elements(By.CSS_SELECTOR, "#browse-results > .row > div")
# 데이터프레임으로 만들기
data = []
for element in elements:
data.append({
"title" : element.find_element(By.CSS_SELECTOR, "h4 > .ga-link").text,
"link" : element.find_element(By.CSS_SELECTOR, "h4 > .ga-link").get_attribute("href"),
})
df = pd.DataFrame(data)
df.tail(2) # 36개의 영상에 대한 제목,링크 데이터 수집
# title link
# 34 두려움을 극복하기 위한 올림픽 챔피언의 사고방식 https://www.ted.com/talks/allyson_felix_an_oly...
# 35 바퀴벌레를 없애는 것은 왜 이렇게 어려울까요? - 아메야 곤달레카르 https://www.ted.com/talks/ameya_gondhalekar_wh...
# 브라우저 종료
driver.quit()
브라우저를 열고 TED 사이트로 이동한 뒤 언어 선택박스에서 한국어를 고르고 영상의 제목과 링크를 찾아 데이터프레임으로 만들어주었다.
selenium에서 엘리먼트를 한 개만 선택할 때와 여러개를 선택할 때 쓰는 함수가 다르니 주의하자
- select_one() : 한개만 선택
- select() : 여러개 선택
위의 코드에서는 h4태그 하위의 ga-link 클래스 요소들의 텍스트 데이터는 모두 title로,
h4 태그 하위의 ga-link 클래스 요소들의 href 속성값들은 모두 link로 저장해주었다.
태그의 속성값을 갖고올 때는 get_attribute()를 사용한다.
[ Headless하게 셀레니움 사용하기 ]
Headless
- 브라우저를 화면에 띄우지 않고 메모리 상에서만 브라우저를 실행하여 크롤링 하는 방법
- 서버 컴퓨터 등과 같이 windows가 지원되지 않는 환경에서 selenium 사용이 가능해짐
만약 브라우저를 띄울 수 없는 환경에서 크롬 브라우저를 열려고 한다면 webdriver.Chrome() 부분에서 문제가 생길 것이다.
headless 설정을 해 주고 셀레니움을 사용하여 TED 홈페이지의 문구를 갖고오는 코드를 작성해보았다.
# headless 설정
options = webdriver.ChromeOptions()
options.add_argument("headless") # 옵션 설정
driver = webdriver.Chrome(options=options)
driver.get("https://ted.com/talks")
sub_title = driver.find_element(By.CSS_SELECTOR, "#banner-secondary").text
driver.quit()
sub_title
# 'Join TED Recommends to get the best ideas, selected just for you'
3. 네이버 중고나라 게시글 데이터 수집 (iframe태그)
네이버 중고나라에서 원하는 상품을 검색했을 때 뜨는 게시글들을 수집하려고 한다.
중고나라의 게시글 엘리먼트들은 iframe 태그 안에 들어 있기 때문에 앞서 했던 방식과는 조금 다르게 selenium을 사용해야 한다.
실습 코드
from selenium import webdriver
from selenium.webdriver.common.by import By
url = 'https://cafe.naver.com/joonggonara.cafe'
keyword = "맥북"
# 1. 크롬 열고 중고나라 이동
driver = webdriver.Chrome()
driver.get(url)
# 2. 검색창에 "맥북"입력
driver.find_element(By.CSS_SELECTOR, "#topLayerQueryInput").send_keys(keyword)
# 3. "맥북" 검색
driver.execute_script("searchBoard();")
# 4. iframe으로 driver 이동
iframe = driver.find_element(By.CSS_SELECTOR, "#cafe_main") # iframe 객체 선택
driver.switch_to.frame(iframe) # frame 전환
# 5. 게시글 요소 찾기
selector = ".article-board > table > tbody > tr"
elements = driver.find_elements(By.CSS_SELECTOR, selector)
# 6. 제목과 작성자 데이터 수집한 뒤 데이터프레임으로 변환
data = []
for element in elements:
data.append({
"title" : element.find_element(By.CSS_SELECTOR, '.article').text,
"writer" : element.find_element(By.CSS_SELECTOR, '.p-nick').text,
})
df = pd.DataFrame(data)
df.tail(2)
# title writer
# 13 2021 M1 맥북프로 16인치 스페이스그레이 흐루두두
# 14 맥북에어m1 16g 512 스페이스그레이+매직마우스2+파우치+거치대+독+허브 증정 lyc891010
# 7. 원래 default frame으로 이동
driver.switch_to.default_content()
# 8. 웹브라우저 종료
driver.quit()
키워드를 검색한 뒤, 바로 게시글의 엘리먼트로 접근하면 아무 데이터도 갖고오지 못하기 때문에 iframe으로 드라이버를 이동시켜주는 작업이 필요하다.
그 뒤에 엘리먼트로 접근하면 정상적으로 접근할 수 있는 것을 볼 수 있다.
작업이 끝난 뒤에는 원래의 default frame으로 다시 돌아준다.
참고로 키워드 검색 후 검색 버튼을 누를 때 검색 버튼 요소로 직접 접근하여 click()하는 방법 말고도 해당 버튼태그의 자바스크립트 코드를 바로 실행시키는 방법도 있는데 이 방법이 더 빠르다고 한다.
개발자 도구로 살펴봤을 때 중고나라의 검색 버튼을 누르면 onclick 속성에 지정된 searchBoard()함수가 호출되는 것을 확인할 수 있었다. 따라서 execute_script()를 통해 자바스크립트 코드를 직접 실행시켜주었다.
4. xpath - 네이버 연관검색어 수집
정적 페이지에서 데이터를 수집할 때 css selector를 사용하는 방법 말고도 xpath를 사용할 수 있다.
xpath 역시 css 선택자와 같이 html element를 선택하는 방법 중 하나이다.
파이썬 코드로 웹페이지의 데이터를 수집하는 프레임워크인 scrapy를 사용해서 이전에 했던 네이버 연관검색어 수집을 간단하게 실습해보았다.
네이버에 "kt"를 검색했을 때 하단의 연관검색어 10가지를 크롤링해주었다.
# scrapy 설치
!pip install scrapy
import scrapy, requests
from scrapy.http import TextResponse
# 네이버에 "kt" 검색
query = "kt"
url = f'https://search.naver.com/search.naver?query={query}'
response = requests.get(url)
# TextREsponse 객체 생성
dom = TextResponse(response.url, body=response.text, encoding="utf-8")
dom.xpath('//*[@id="nx_footer_related_keywords"]/div/div[2]/ul/li/a/div')
keywords = dom.xpath('//*[@id="nx_footer_related_keywords"]/div/div[2]/ul/li/a/div/text()').extract()
print(keywords)
# ['삼성전자', 'kt 고객센터', 'kt 인터넷', 'ky', '환율', 'kt 대리점', 'kr', '날씨', 'SKT', 'kt 고객센터 전화번호']
코드를 설명하기 전에 xpath의 문법을 알아보자
[ xpath syntax ]
개발자 도구 > 엘리먼트 태그 선택 > 우클릭 > 복사 > xpath복사를 통해 확인해보면
//*[@id="nx_footer_related_keywords"]/div/div[2]/ul/li[1]/a/div
와 같은 형식의 선택자를 볼 수 있다.
- // : 최상위 엘리먼트
- * : 모든 하위 엘리먼트 : css selector(.wrap p)와 같은 기능
- [@id="nx_footer_related_keywords"] : 속성값으로 엘리먼트 선택
- /: 한단계 하위 엘리먼트 : css selector(.wrap > p)
- [n] : n 번째 엘리먼트
scrapy의 TextResponse()는 갖고온 웹페이지를 DOM 구조로 만들어서 xpath를 사용하여 엘리먼트를 선택할 수 있도록 도와준다.
위의 코드를 보면 받아온 응답을 dom 객체인 TextResponse로 만들어서 원하는 엘리먼트 태그를 찾아준다.
xpath를 사용하면 반복문 없이 해당하는 모든 엘리먼트를 선택 가능하다.
ul태그 아래의 li태그들이 각 연관검색어 요소들을 나타내는데, 일반적인 css 선택자를 사용했다면 해당 엘리먼트들을 받아온 뒤 반복문을 통해 엘리먼트 하나씩 텍스트 데이터를 추출해서 리스트에 담아주는 작업을 했어야 한다.
하지만 xpath를 사용한다면 아래의 코드를 통해 한번에 모든 li태그 요소들의 text 데이터를 리스트로 받아올 수 있다.
keywords = dom.xpath('//*[@id="nx_footer_related_keywords"]/div/div[2]/ul/li/a/div/text()').extract()
5,6번 내용은 어려워서 간단하게만 정리하고 공부를 더 해야할 것 같다.
5. iterator와 generator (yield 사용)
iterable
: list, tuple 등과 같이 순서가 있는 데이터 집합
- iterator : next 함수를 실행하여 값을 발생시키는 값 생성기
- generator : iterator를 간단하게 구현한 문법
6. scrapy 프레임워크
scrapy
: 파이썬에서 데이터를 수집하게 해주는 프레임워크이며 비동기 방식으로 데이터를 수집하기 때문에 데이터 수집 속도가 빠르다.
[ G마켓 베스트셀러 상품 데이터 수집 ]
scrapy 프레임워크를 사용해서 G마켓의 베스트셀러 상품 데이터를 수집해보았다.
- scrapy 프로젝트 생성
!scrapy startproject gmarket
# New Scrapy project 'gmarket', using template directory 'c:\users\user\anaconda3\lib\site-packages\scrapy\templates\project', created in:
# C:\Users\User\KT_AIVLE_School\2주차\웹크롤링\day3\gmarket
# You can start your first spider with:
# cd gmarket
# scrapy genspider example example.com
- 프로젝트 폴더 내용 확인
!tree gmarket /f
# 폴더 PATH의 목록입니다.
# 볼륨 일련 번호가 000000AB 7C6C:FC35입니다.
# C:\USERS\USER\KT_AIVLE_SCHOOL\2주차\웹크롤링\DAY3\GMARKET
# │ scrapy.cfg
# │
# └─gmarket
# │ items.py
# │ middlewares.py
# │ pipelines.py
# │ settings.py
# │ __init__.py
# │
# └─spiders
# __init__.py
- items.py : 수집할 데이터의 구조 정의
- middlewares.py : 데이터를 수집할 때 headers 정보와 같은 내용을 설정
- pipelines.py : 데이터를 수집한 후에 코드 실행 정의
- settings.py : 크롤링 설정 (크롤링 시간 텀, robots.txt 규칙 지킬 지 안지킬 지 등)
- spiders디렉토리 : 크롤링 절차 정의
작성 코드가 어려워서 정리는 못했는데 당장은 몰라도 되는 내용이니 xpath, scrapy, iterator, generator 같은 내용들은 나중에 다시 보자
'KT AIVLE School' 카테고리의 다른 글
(3주차 - 22.08.09) 데이터 처리2 (0) | 2022.08.09 |
---|---|
(3주차 - 22.08.08) 데이터 처리1 (0) | 2022.08.08 |
(2주차 - 22.08.04) 웹크롤링2 (0) | 2022.08.04 |
(2주차 - 22.08.03) 웹크롤링 1 (0) | 2022.08.03 |
(2주차 - 22.08.02) Python 라이브러리 활용 [데이터 분석] 2 (0) | 2022.08.02 |