본문 바로가기
정리/정보 요약

[정보] 정적 웹크롤링

by 멘멘 2021. 7. 19.

- 아래 내용은 학교 수업 내용을 정리한 것임 (시험공부용)

- 선생님의 자료와 부교재 <데이터분석 실무 with 파이썬>을 주로 참고함

- 오류 지적, 질문 등 언제나 환영

 

 


1. 개념

1) 파이썬

파이썬 (Python)

- 빠르게 성장하는 언어로 데이터 분석 분야에서 많이 활용됨.

 

빅데이터 처리에서의 파이썬의 장점

1. 이해하기 쉽고 유연한 문법으로 인한 좋은 접근성

2. 빅데이터 처리 언어로서의 많은 커뮤니티 형성

3. 가독성이 좋고 간결, 잘 갖춰진 스탠다드 라이브러리

4. 데이터 분석 관련 패키지 제공, 라이브러리 무상 공급

 

+) 라이브러리

BeautifulSoup

: html, xml 파일에서 데이터를 가져오기 위한 파이썬 라이브러리

 

urllib.request   /   requests

: 둘 다 크롤링을 할때 많이 사용되는 라이브러리로 둘의 차이가 정확하게 뭔지 궁금해서 알아보았는데,

반환 형태와 에러 표시에서의 차이가 있는 듯하다. 둘이 큰 차이는 없으며 requests를 많이 사용한다고 한다.

 

import urllib.request
res = urllib.request.urlopen("http://www.naver.com/")

import requests
#둘다 url 뒤는 요청 없으면 생략 가능
#requests.get(url, params = None, **kwargs)
#requests.post(url, data = None, json = None, **kwargs) 
r = requests.get('http://www.naver.com/')

예제에서는 params_d = {'a' : 'b', 'c' : 12} 같은 딕셔너리를 만들어서 params나 data에 전달하기도 했다. 하지만 중요한 부분은 아닌거 같아 이하생략,,,

 


2) 크롤링, 스크래핑, 파싱

크롤링 (crawling)

: 웹 페이지의 하이퍼링크를 순화하며 웹페이지를 다운로드하는 작업

 

스크래핑 (scraping)

: 다운로드한 웹 페이지에서 필요한 컨텐츠를 추출하는 작업.

웹 페이지를 구성하고 있는 html 태그의 콘텐츠속성 값을 읽는 작업.

 

파싱 (parsing)

: 구문 분석, 즉 문장을 구성 성분으로 분해하여 위계 관계를 분석해 문장의 구조를 결정하는 것

 => 데이터를 조립해 원하는 데이터를 빼내는 프로그래밍을 하는 것

 


3) 웹 용어

URL (Uniform Resource Locator)

: 네트워크 상에서 자원이 어디있는지를 알려주기 위한 규약

컴퓨터 네트워크와 검색 메커니즘에서의 자원의 위치를 지정하는 문자열

 

URI (Uniform Resource Identity)

: 웹 사이트에 요청하고자 하는 대상의 패스정보와 파일명으로 구성 (파일명 생략 시 기본값으로 index.html 사용)

 

HTTP (HyperText Transter Protocol)

: 웹상에서 클라이언트와 서버간에 정보를 주고 받을 수 있는 통신 규약 (기본 = 80번 포트)

웹클라이언트에서 웹서버에 http 요청을 전달할때 요청방식(GET,POST)을 명시함

GET 방식 POST 방식
브라우저에서 직접 요청하려는 페이지의 URL 문자열을 입력하여 요청  브라우저 상 전달 방식이 보이지 않고 form 태그를 통한 요청 
URI에 보임 URI에 보이지 않으며, method = get으로도 가능
https://movie.daum.net/moviedb/main?movieId=126260 <body> <form action = main.php method = post> ...

 

HTML : 웹페이지를 만들때 사용하며 태그를 사용

CSS : HTML과 같은 마크업 언어가 실제 표시되는 방법을 기술

   - css 선택자(Selector): 스타일 적용을 위해 대상 태그를 선택하는 방법

* javasrcipt를 이용해 웹페이지가 동적으로 구성되는 경우 selenium 등을 추가로 사용해야함 (추후 포스팅 예정)

 


2. html 태그 명령

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>TEST</title>
	</head>
	<body>
		<!-- h 태그 -->
		<h1> h1 </h1>
		<h2> h2 </h2>
		<h3> h3 </h3>
		<h4> h4 </h4>
		<h5> h5 </h5>
		<h6> h6 </h6>
		
        	<!--ul: 번호x 목록 li:나열 -->
		<ul>
			<li>목록1</li>
			<li>목록2</li>
		</ul>


	</body>
</html>

 

 

 

<h1>태그는 글씨를 크게 나타내는 제목을 표시하는 태그

(숫자가 작을수록 크기가 커짐, 6까지 있음)

 

<ul> : 번호 없는 목록, <li> : 목록 나열

 

 

 

 

 

 

 


3. Beautiful Soup 사용하기

html_doc = """
<!DOCTYPE html>
<html> 
	<head> 
		<meta charset="utf-8"> 
		<title>TEST</title> 
	</head> 
	<body> 
		<h1 style='color : blue'>시험</h1>
		<h2 style='color : blue'>1일차</h2>
		<ul>
			<li>영어1</li>
			<li><strong>수학2</strong></li>
		</ul>
		<p align="center", class = "a"> 가운데 정렬</p>
		<p align="right", class = "b test"> 오른쪽 정렬</p>
		<p align="left"> 왼쪽 정렬</p>
		<img src="https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAxODAxMjlfMTMx%2FMDAxNTE3MjM1NjI5Mjk2.G405bTHQmrH1r_hcC8sJ2NGl05TAoNKrP-o9qrXhHFkg.VpqupT32L8x4UuOLlFkkt780Jemt7YqAHrZQ28hzrFUg.JPEG.heima916%2FIMG_0898.jpg&type=sc960_832" width="500">
	</body>
</html>"""

대충 html 코드를 짜서 넣어보았다. 위 html 코드만 따로 실행하면 다음과 같이 뜬다.

 


1) 요소 출력

from bs4 import BeautifulSoup
bs = BeautifulSoup(html_doc,'html.parser')
print("[h1]")
print(type(bs.h1.contents),':',bs.h1.contents)
print("[ul]")
print(type(bs.ul.contents),':',bs.ul.contents)
print("[img]")
print(type(bs.img.contents),':',bs.img.contents)
print("[p]")
print(type(bs.p.contents),':',bs.p.contents)
print("[ul.strong]")
print(type(bs.ul.strong.contents),':',bs.ul.strong.contents)

출력결과

 

contents : <태그명령>내용</태그명령>의 내용을 추출함. contents[6]은 상위태그의 콘텐츠 중 7번째 자식 콘텐츠를 의미함.

 

 

h1은 시험, ul은 안에 있는 li 2개가 나온 것을 확인할 수 있다.

img 태그의 경우 내용이 존재하지 않아 출력되지 않았고 여러개 존재하는 p태그는 맨처음 한가지만 출력되었다.

ul.strong과 같이 여러개의 태그로 감싸져 있는 내용도 추출할 수 있다.

 


 

2) find, find_all

 

BeautifulSoup의 find와 find_all에 대해 알아보자.

  find find_all
형태 1) find('태그명')
2) find('태그명', {'class':'클래스명'})
   find('태그명', class_='클래스명')
find_all('태그명')
반환 태그 형태로 반환 ResultSet로 반환

 

from bs4 import BeautifulSoup
bs = BeautifulSoup(html_doc, 'html.parser')
print(type(bs.find('p')))
print(type(bs.find_all('p')))
print(type(bs.find('strong')))

반환 형태를 확인해보면 find는 tag, find_all은 ResultSet임을 확인할 수 있다.

 

print(bs.find('img'))
ptags = bs.find_all('p')
pst = bs.find('strong')
print(pst)
print(ptags)

결과를 보면 알 수 있듯 find를 이용할 경우 태그 형태로, find_all을 이용한 경우 리스트(?) 형태로 출력됨을 알 수 있다.

 

for tag in ptags:
	print(tag.text)
ptag = bs.find_all('img')
print(ptag)

find_all에서 태그의 내용을 출력하고 싶다면 다음과 같이 for문과 반환변수.text를 사용할 수 있다.

반환변수.text : 태그 사이의 콘탠츠를 가져옴 (=> 반환변수.get_text() 랑 동일)

 


 

3) requests

 

requests.get()으로 코드 파싱하기

-> soup에서 html.text처럼 text 확장자를 붙여줘야 한다.

-> get으로 코드를 파싱할 경우 uri에 한글이 있어도 가능하다.

from bs4 import BeautifulSoup
import requests
html = requests.get("http://www.naver.com/")
soup = BeautifulSoup(html.text,'html.parser')
print(type(soup))
print(soup)


 

4) select_one, select

 

select_one select
지정 태그 첫줄만 불러와서 태그로 반환 지정 태그 모든 내용을 리스트 형식으로 불러옴
get_text문 / 반환변수.text for문과 get_text문 혹은 반환변수.text
반환변수[인덱스번호].text

 

css selector
태그지정 h1
하위태그 상세 지정 ul > strong
클래스 지정 .클래스명  /  태그.클래스명
클래스명 내 띄어쓰기 존재 띄어쓰기 -> . 로 치환
아이디 지정 #아이디명

 

from bs4 import BeautifulSoup
bs = BeautifulSoup(html_doc, 'html.parser')
print(type(bs.select('p')))
print(type(bs.select('strong')))
print(bs.select_one('p'))
print(bs.select('.a')) #클래스명
#클래스에 띄어쓰기 존재
text = bs.select_one('.b.test')
print(test.text)

stag = bs.select('strong')
#print(stag.text) 오류 발생(리스트)
for tag in stag:
	print(tag.test)
    
#혹은 select_one으로 바꾸기

*find와 select의 차이점!

find select
bs,find('ul').find('strong')
bs.find('div', class_='col col1ergebnis') #띄어쓰기 이해 쉬움
bs.select_one('li > strong')
#찾는 속도 빠름, 상세태그 지정 편리 / 띄어쓰기 이해 어려움
bs.find('p', class_='a') bs.select('.a') #클래스 지정 없이 .클래스명
tag = bs.find('p', class_='a')
print(tag.text)
tag = bs.select('.a')
print(tag[0].text) #혹은 for문 돌리기

5) re.sub

import re 필요! 불필요한 문자를 대체해줌

(ex) re.sub("[\n\t]",'',변수.text) #re.sub(불필요한 문자,빈따옴표,바꿀문자)

 

import re
ul = bs.select('ul > li')
for ui in ul:
	ui = re.sub(["\n\t"],'',str(ui.text))
    print(ui)

다음과 같이 사용하면 불필요한 탭이나 줄바꿈 없이 순수 문자만 읽어들일 수 있다.

 


6) html table

(전략)
<table border = 1>
<tr>
<td> 1 </td> <td> 2 </td> <td> 3 </td>
</tr>
<tr>
<td> 4 </td> <td> 5 </td> <td> 6 </td>
</tr>
</table>
(후략)

대략 위와 같은 코드는 대충 아래와 같은 모양새의 표로 나타난다.

1 2 3
4 5 6

<tr>은 줄바꿈(행) <td>는 칸으로 생각할 수 있다.

 

import requests
from bs4 import BeautifulSoup

html = request.get('대충 웹주소')
html = html.content.decode('utf-8')
bs = BeautifulSoup(html, 'html.parser')
print(bs.select('table')[0].text)

위와 같은 코드로 table을 출력할 수 있다. 위 표를 읽어들었다고 생각하면 결과는

123

456

이 된다.


7) a 링크 콘텐츠

<a href = "주소"> 클릭내용 </a>   의 형태


8) 소스 검사

 

마우스 우클릭 > 검사 또는 CTRL+SHIFT+I

위 버튼 클릭후 요소 선택 > 우클릭 후 selector 복사 (태그명령 + 클래스명) / 전체 xpath복사 (태그명령)

 


 

정적 웹크롤링 요약 끝! 추후 글 다듬으러 오겠습니당 :D

'정리 > 정보 요약' 카테고리의 다른 글

[정보] 인스타 크롤링 해보기  (0) 2021.07.20
[정보] 정규식 표현  (0) 2021.07.20
[정보] 동적 웹 크롤링  (0) 2021.07.20

댓글