본문 바로가기
코딩 어쩌구/Data

[edwith] 파이썬을 이용한 웹 스크래핑 (1)

by annmunju 2021. 5. 3.

www.boostcourse.org/cs201/lecture/493645/?isDesc=false

 

파이썬을 이용한 웹 스크래핑

부스트코스 무료 강의

www.boostcourse.org

 

제 11장 정규식

 

1. 정규식을 이용한 패턴 찾기

 - 기호로 되어있어 효과적, 하나의 언어. 특수 문자로 이뤄진 언어로 문자만을 사용해 프로그래밍 하는 개념(형식언어)

 - 요약

^           라인의 처음을 매칭

$            라인의 끝을 매칭

.             임의의 문자를 매칭 (와일드 카드)

\s          공백 문자를 매칭

\S         공백이 아닌 문자를 매칭

*            바로 앞선 문자에 적용되고 0 혹은 그 이상의 앞선 문자와 매칭을 표기함.

*?          바로 앞선 문자에 적용되고 0 혹은 그 이상의 앞선 문자와 매칭을 탐욕적이지 않은 방식으로 표기함.

+           바로 앞선 문자에 적용되고 1 혹은 그 이상의 앞선 문자와 매칭을 표기함

+?          바로 앞선 문자에 적용되고 1 혹은 그 이상의 앞선 문자와 매칭을 탐욕적이지 않은 방식으로 표기함.

[aeiou]    명세된 집합 문자에 존재하는 단일 문자와 매칭. “a”, “e”, “i”, “o”, “u” 문자만 매칭되는 예제

[a-z0-9]    - 기호로 문자 범위를 명세할 수 있다. 소문자이거나 숫자인 단일 문자만 매칭되는 예제.

( )         괄호가 정규표현식에 추가될 때, 매칭을 무시한다. 하지만 findall()을 사용 할 때 전체 문자열보다 매칭된 문자열의 상세한 부속 문자열을 추출할 수 있게 한다.

 - 정규식 모듈 "re" (import re 명령어로 라이브러리 불러오기)

 

2. 정규식을 이용한 패턴 추출 : re.findall()

import re
x = 'My 2 favorite numbers are 19 and 42'
y = re.findall('[0-9]+',x)
print(y)

# ['2', '19', '42']

 - Greedy Matching : 'From: Using the : character' 문장에서 '^F.+:' 정규식으로 내용을 찾는다면

     >>> ['From: Using the :'] : +와 *에서 가장 길게 매칭되는 경우를 탐색함.

    > 짧게 바꾸고 싶은 경우 '^F.+?:' 를 씀.

 - 섬세한 문자열 추출 : ( ) 괄호 안 내용만 리턴됨

x = 'From stephen.marquard@uct.ac.za Sat Jan  5 09:14:16 2008'
y = re.findall('^From (\S+@\S+)',x)
print(y)

# ['stephen.marquard@uct.ac.za']

 

3. 정규식을 활용하는 다양한 방법

 From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008

 - 우리가 이전에 활용한 방법

  1) @의 인덱스값을 찾기 (21) > 그 뒤에 바로 나오는 공백 " "의 인덱스 값 찾기 (31) > [21+1 : 31] 출력

  2) 문자열 split 하기 (From / stephen.marquard@uct.ac.za / Sat / Jan / 5 / 09:14:16 / 2008) > 인덱스 값이 [1]인 부분 '@'를 기준으로 split 하기 (stephen.marquard/uct.ac.za) > 필요한 부분 [1] 출력

 

 - 정규 표현식으로 추출하기

import re 
lin = 'From stephen.marquard@uct.ac.za Sat Jan  5 09:14:16 2008'
y = re.findall('^From .*@([^ ]*)',lin)
print(y)

# ['uct.ac.za']

 - 예제)

mport re
hand = open('mbox-short.txt')
numlist = list()
for line in hand:
    line = line.rstrip()
    stuff = re.findall('^X-DSPAM-Confidence: ([0-9.]+)', line)
    if len(stuff) != 1 :  continue
    num = float(stuff[0])
    numlist.append(num)
print('Maximum:', max(numlist))

 - Escape Character : 지정된 특수문자 그대로 사용하고 싶으면 '\' 붙이면 됨. (\+?, \* 등) 

 


제 12장 HTTP

 

1. 소켓 모듈을 통한 네트워크 연결 (클라이언트와 서버-생활코딩)

  1) 프로토콜(Protocol)
:통신 규약. 쉽게 말해, 서로 대화를 하기 위한 기본적인 약속과 절차들을 의미. 프로토콜이란 주인과 손님 간의 행동양식에 대해 미리 정해진 약속.

  2) TCP/IP
**참고: https://www.joinc.co.kr/w/Site/Network_Programing/Documents/IntroTCPIP
TCP/IP는 컴퓨터끼리의 대화를 위한 통신 규약이다.
    (1) TCP: 통신 제어 규약 Transmission Control Protocol
통신 과정의 오류를 잡기 위한 규약이다. 패킷, 즉 사람으로 치면 우편 편지를 주고 받는 과정에서 손실, 왜곡, 순서 뒤바뀜 등의 오류가 발생할 수 있는데 이때 TCP는 그 오류를 교정하고 순서를 재조합할 수 있도록 해준다.
**짧게 예를 들면, 철수와 영희가 임의의 편지 번호를 정하기로 약속한다. 철수는 100번부터, 영희는 5000번부터. 철수가 편지100번을 영희한테 보내고, 영희가 그걸 받으면 영희는 "편지100번 받음. 101번 기다리겠음"이라는 편지5001번을 보낸다. 그런데 철수가 실수로 편지101번이 아니라 편지 102번을 보내면? 영희는 편지5002번에 "편지101번을 기다리겠음"이라고 보낸다. 철수가 바보 같이 편지103번을 보내면 영희는 다시 "편지 101번을 기다리겠음"이라고 보낸다. 철수는 그제서야 자신의 실수를 깨닫고 101번을 보낸다. 영희는 "편지 104번을 기다리겠음"이라고 답장한다.
    (2) IP: 인터넷 규약 Internet Protocol
주소에 관한 규약이다. 사람이 서로 우편 편지를 보내려면 주소가 있어야 한다. 컴퓨터도 우편 편지, 즉 패킷을 전송하기 위해서는 각자 인터넷 주소를 필요로 한다. 흔히 IP 주소라고 하는 게 이것이다. 보통 192.168.100.100 이런 식으로 표현된다.

  3)소켓
[출처: 위키백과] 네트워크 소켓(network socket)은 컴퓨터 네트워크를 경유하는 프로세스 간 통신의 종착점이다. (...) 네트워크 통신을 위한 프로그램들은 소켓을 생성하고, 이 소켓을 통해서 서로 데이터를 교환한다. 소켓은 RFC 147에 기술사항이 정의되어 있다.

  4) 포트
컴퓨터를 회사로 친다고 하면, 그 회사 안에는 수많은 역할들이 사무실 별로 분업이 되어 있을 것이다. 로그인 담당 부서, 이미지 부서, 이메일 부서 등등.


포트 번호는 쉽게 말해 담당 사무실 부서 "코드 번호"이다. 예를 들어, 로그인을 하고 싶으면 로그인 담당 사무실로 전화

를 걸면 되는데 이 회사는 전화번호가 없고 대신 코드 번호가 있다. 회사 매뉴얼을 뒤져보니, 로그인 담당 부서 코드 번호는 80이다. 그러면 80으로 로그인 요청을 하면 된다. >>>

컴퓨터는 여러 프로세스(기능, 역할)가 있는데 각 프로세스 별로 포트 번호가 할당되어 있다.

 

 - 파이썬에서의 소켓 

연결하기

 

2. HTTP를 이용해 서버에 요청 보내기

 - 애플리케이션 프로토콜 (ex. 메일, 월드 와일드 웹(www))

 - HTTP : 하이퍼텍스트 전송 프로토콜 (HTML, 이미지, 문서 등을 가져옴)

 - 프로토콜 : 규칙

 - 서버로부터 데이터 받기 (요청자가 클릭 > 웹서버를 통해 80번 포트로 연결 요청해 보냄 > HTML형식의 웹페이지로 응답 > 파싱과 렌더링을 통해 보여줌)

 - 인터넷 표준 (IETF라는 기관에 의해 개발됨) : 기준은 RFCs라고 부름 (“Request for Comments”)

 - HTTP 요청을 만드는 법 : 서버 연결 > 문서 요청 (GET http://mungdo-log.tistory.com HTTP/1.0)

 - Telnet : 옛날에 사용되던 프로그램. 소켓을 통해 호스트 포트에 연결할 수 있는 프로그램. 

$ telnet mungdo-log.tistory.com 80
Trying 12.345.67.890...
Connected to mungdo-log.tistory.com.Escape character is '^]'.
GET http://mungdo-log.tistory.com HTTP/1.0

HTTP/1.1 200 OK
Date: Thu, 26 Jan 2021 11:13:52 GMT
Last-Modified: Thu, 26 Jan 2021 14:25:43 GMT
Connection: close
Content-Type: text/html

<h1>The First Page</h1>
<p>If you like, you can switch to
the <a href="http://mungdo-log.tistory.com/page2.htm">Second
Page</a>.</p>
Connection closed by foreign host.

 

3. 파이썬을 이용해 웹 데이터 읽어오기

import socket

mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('data.pr4e.org', 80))
cmd = 'GET http://data.pr4e.org/romeo.txt HTTP/1.0\r\n\r\n'.encode()
mysock.send(cmd)

while True:
    data = mysock.recv(512)
    if (len(data) < 1):
        break
    print(data.decode(),end='')
mysock.close()

<실습> 소켓

import socket

mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('data.pr4e.org', 80))
cmd = 'GET http://data.pr4e.org/romeo.txt HTTP/1.0\r\n\r\n'.encode()
mysock.send(cmd)

while True:
    data = mysock.recv(512)
    if (len(data) < 1):
        break
    print(data.decode(),end='')
mysock.close()

 

4. 문자를 표현하는 방법 및 인코딩과 디코딩

- ASCII (문자 기준(8bits = 1byte) 한문자에 1바이트 할당) > 유니코드 > UTF-32(한문자 4byte 할당 - 용량 문제 발생) > UTF-16 > UTF-8(ASCII 포함) 

- 네트워크에서 주로 사용하는 문자는 유니코드로 인코딩 되어 있음. 이걸 UTF-8로 인코딩. > 네트워크로 전송 > 데이터를 받음(byte 형식으로 되어있음) > 내용을 출력 전에 디코딩 해야함. 

 

5. urllib를 이용해 웹 데이터 읽어오기

- import urllib.request

counts = dict()
fhand = r.urlopen('http://www.py4inf.com/code/romeo.txt')
for line in fhand:
  words = line.split()
  for word in words:
    counts[word] = counts.get(word,0) + 1
print (counts)

 

 

728x90