데이터 채굴하기 1편: 웹 스크래핑
정오늘의 공부 내용, 웹 스크래핑
참고 유튜브: 나도코딩
이번 게시물은 웹 스크래핑을 하기 위한 이론편이다.
웹 스크래핑?
웹 페이지에서 내가 원하는 부분만 떼어오는 것
웹 크롤링이랑 뭐가 다른데?
웹 크롤링은 페이지 내의 링크들을 따라가면서 모~든 내용을 가져오는 것.
마구잡이로 가져옴
데이터를 채굴하는 현장에서 매우 빈번하게 쓰이는 기술이나,
크롤링/스크래핑으로 가져온 데이터는 휘발성이 강하며 변화가 잦다.
웹의 구성
1. HTML : 집의 뼈대
2. CSS : 인테리어
3. JS (JavaScript) : 사람의 다양한 활동(살아있게 하는 것) → 창문 여닫기, 불 끄고 켜기 등
HTML
Hyper Text Markup Language
<html/> : element
<html></html> : 여는 태그와 닫는 태그로 구성됨 (위와 같은데 두번 써줌)
※ vscode에서 html 파일 생성하는 법
1) .html 파일 생성하기
2) open in brower: extension 설치하기
3) 파일 우클릭해서 브라우저 선택하고 열기 가능
* 보통 웹페이지 구성
<html>
<head> : 제목
<title> 홈페이지 제목 </title>
<meta charset="utf-8"> #한글 깨짐 방지
</head>
<body> : 본문
<h1> 안녕하세요? </h1>
<a href = "http://www.google.com">구글로 이동하기</a> #하이퍼링크 이동
</body>
</html>
구현하면 이렇다!
※ 공부 시 참고하면 좋은 사이트: w3school
Xpath
어떤 element를 지칭하는지 확실히 하기 위해 사용
element간의 부모-자식 관계가 있음
같은 depth의 경우 연결되어 있는 형제(sibling) 노드라고 부름
※ vscode에서 Xpath 사용법
1) .txt 파일 생성하기
※ 위치찾기
1) /태그/태그/태그/.../[2] (인덱스)
2) //*[@학번="1-1-5"] (모든 문서에서 고유한 값을 찾음)
Requests
웹 페이지 정보를 가져오기 위해 필요한 라이브러리
pip install requests
import requets
res = requests.get("url긁어오기")
print("응답코드: ", res.status_code)
#200이면 정상
##403이면 이 페이지 접근 권한 없음
if res.status_code == requests.codes.ok(또는 200):
print("정상입니다")
else:
print("문제가 발생했습니다.[에러코드 ",res.status_code, "]")
#다른 방법
res.raise_for_status() #문제가 생겼을 때 오류를 뱉고 프로그램 종료시킴
print("웹 스크래핑을 진행합니다.")
정규식 기본 1 - compile, match
.py 파일 생성하여 작성(.ipynb)
주민번호, 차량번호, 이메일 주소와 같이 특정 양식에 부합하는지 검사할 수 있음
921201 - 1111111 (O)
abcdefg - 1111111 (X)
1) compile
p = re.compile("원하는 형태") : 정규식 구현
import re #정규식 라이브러리
p = re.compile("ca.e")
# . (ca.e) : 하나의 문자를 의미 > care, case, cafe
# ^ (^de) : 문자열의 시작 > desk, destination
# $ (se$) : 문자열의 끝 > case, base
m = p.match("care"). #패턴과 매치되는지 확인
print(m.group()) #매칭되지 않으면 에러 발생
#매칭되면 입력한 그 단어를 뱉음. 이 경우 care 출력됨
m = p.match("careless")
print(m.group()) #care 출력됨
#match: 주어진 문자열의 처음부터 매칭을 확인
if m:
print(m.group())
else:
print("매칭되지 않음")
정규식 기본 2 - search, findall
1) search
- match: 주어진 문자열의 처음부터 매칭을 확인
- search: 주어진 문자열 중에 일치하는게 있는지 확인
p = re.compile("ca.e")
m = p.search("good care") #search를 써서 처음부터 탐색(match)하지 않고 포함되어 있는지 확인함
print(m.group()) #care 출력됨
print(m.string) #good care 출력됨
- group(): 일치하는 문자열을 반환 (careless 입력 > care 반환)
- string: 입력받은 문자열을 반환 (careless 입력 > careless 반환)
- start(): 일치하는 문자열의 시작 index (careless 입력 > 0) *care(위치가 0부터 4이전까지)
- end(): 일치하는 문자열의 끝 index (careless 입력 > 3) *care(위치가 0부터 4이전까지)
- span(): 일치하는 문자열의 시작 / 끝 index (careless 입력 > (0, 3))
m = p.search("careless") #careless에 ca.e가 있는지 확인
def print_match(m):
if m:
print("m.group():", m.group())
print("m.string:", m.string)
print("m.start():", m.start())
print("m.end():", m.end())
print("m.span():", m.span())
else:
print("매칭되지 않음")
2) findall
일치하는 모든 것을 리스트 형태로 반환
위의 경우 careless, good care에서 각각 care가 일치하므로 리스트로된 care가 반환됨
User Agent
브라우저는 사이트에 접근하는 헤더(사용자) 정보를 수집할 수 있다.
각 헤더 정보가 어떤 디바이스냐(모바일, PC, Pad)에 따라 다른 페이지를 제공한다.
그런데 사람이 아닌 웹 스크롤링(PC)가 접근하는 경우?
접근하는 자의 정보를 확인해서 접속을 차단할 수 있다.
requests를 이용할 경우 403 에러가 뜨면서 html 정보를 바로 가져오지 못하는 것도 예시임
1) User Agent String
What is my user agent? - WhatIsMyBrowser.com 여기서
내 브라우저에서 접속하는 유저 에이전트 정보를 볼 수 있음
이 주소를 복사하기
2) headers 변수 생성
header 정보를 수작업으로 지정하기 위함.
requests를 하기 전에 headers = {"User-Agent" : "복사한 주소"} 이렇게 지정하기
dict형식으로 변수를 만들어줌
3) res = requests.get(url, headers)
기존과 달리 headers 파라미터를 지정해줌으로써 403(접근권한 없음) 에러가 뜨지 않도록 함