Python에서의 다중 연결 처리
- 기존 single client와 single server 간의 연결만을 처리했다면, 하나의 server가 많은 client와 연결을 하는 방법이다
- 동시성을 해결하는 방법:
1) fork (프로세스 복제)
2) threads (프로세스 내의 여러 개의 동작)
3) asynchronous I/O (selector 기반)
from socket import *
import selectors # 파일디스크립터의 처리 이벤트를 모니터링 해주는 모듈
sel = selectors.DefalutSelector() #selector생성
s = socket(AF_INET, SOCK_STREAM) #소켓 생성
s.bind((host, port))
s.listen()
s.setblocking(False) #소켓을 non-blocking모드로 변경
# selector에 관찰할 소켓등록(소켓, 기다리는 이벤트명)
sel.register(s, selectors.EVENT_READ, data=None) # Read요청이 오면 나를 깨워달라
while True:
events = sel.select(timeout=None) # 등록된 소켓 중 처리해야할 event가 있는 소켓검사 (timeout: 기다릴 시간설정)
for key, mask in events: # key: 어떠한 fd인지, mask: 어떠한 이벤트발생인지
if key.data is None: # s소켓에 처리해야할 이벤트가 있는경우
accpet_wrapper(key.fileobj) #연결요청 처리, key.fileobj는 client연결을 나타내는 소켓객체
else:
service_connection(key, mask) #일반적인 클라이언트와의 요청처리
def accpet_wrapper(sock):
conn, addr = sock.accept() #연결요청 처리
print('from', addr)
conn.setblocking(False) # 클라이언트와의 연결도 non-blocking모드로 셋팅
data = types.SimpleNamespace(addr=addr, inb=b'', outb=b' ') #data생성
events = selectors.EVENT_READ | selectors.EVENT_WRITE #관찰할 event는 READ,WRITE
sel.register(conn, events, data=data) #selector에 등록
def service_connection(key, mask): # key: fd, mask: 어떠한 이벤트인지
sock = key.fileobj #소켓 가져오기
data = key.data #데이터 가져오기
if mask & selectors.EVENT_READ: #읽는 경우
recv_data = sock.recv(1024) #소켓으로부터 읽기
if recv_data: #데이터가 null이 아니면
data.outb += recv_data
else:
sel.unregister(sock) #selecotr에서 연결되어있는 소켓 제거
sock.close() #소켓 닫기
if mask & selecotrs.EVENT_WRITE: #쓰는 경우
if data.outb:
sent = sock.send(data.outb) #소켓으로 보내기
data.outb = data.outb[sent:]
Python에서의 HTTP 요청
- socket 이용
import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #소켓 생성
mysock.connect(('data.pr4e.org', 80)) #80번 포트의 웹서버 접근
cmd = 'GET http://data.pr4e.org/romeo.txt HTTP/1.0\n\n'.encode()
mysock.send(cmd) #소켓을 통해 요청
while True:
data = mysock.recv(512) #서버에서 보내주는 웹페이지 받기
if (len(data) < 1): #더이상 읽어올 데이터가 없으면
break
print(data.decode())
mysock.close()
- urllib 이용
: HTTP는 굉장히 많이 쓰이므로 소켓을 다루고 웹페이지를 불러오는 라이브러리가 있음
# 웹페이지에서 단어의 출현 빈도 계산하기
import urllib.request, urllib.parse, urllib.error
fhand = urllib.request.urlopen('http://data.pr4e.org/romeo.txt') #해당url을 오픈한후 읽어와 디스크립터 반환
for line in fhand: # 원격에 있는 txt파일을 줄단위로 처리
words = line.decode().split()
for w in words:
counts[w] = counts.get(w, 0) + 1
print(counts)
웹 스크래핑
- 프로그램이나 스크립트가 브라우저처럼 행동하며, 페이지를 살펴보고 정보를 추출,조사하는 것을 말함
- 검색엔진은 웹페이지를 스크래핑하는 것. (크롤링이라고도 부름)
- 스크래핑하는 이유?
소셜데이터를 가져오기, 외부로 내보내는 기능이 없는 시스템에서 데이터 가져오기
사이트를 모니터링하며 새로운 정보 감지, 검색엔진의 db를 구축하기 위해
BeautifulSoup
- urllib + html parsing
- 설치 명령어: pip install beautifulsoup4
import urllib.request, urllib.parse, urllib.error, requests # 웹페이지 열기, 가져오기
from bs4 import BeautifulSoup # HTML태그 파싱
url = input('Enter: ')
headers = {'user-agent': 'Mozilla/5.0'} # 사이트 정책
page = requests.get(url, headers = headers) # 페이지요청에 대한 정보
soup = BeautifulSoup(page.content, 'html.parser', from_encoding='utf-8') #파싱결과 리턴
tags = soup('a')
for tag in tags: # <a>태그 보면서
print(tag.get('href', None)) # <a href="">의 값 꺼내기
'Study > Python' 카테고리의 다른 글
[Python #8] Database (0) | 2021.12.14 |
---|---|
[Python #6] Network (0) | 2021.11.24 |
[Python #5] Class, Module, Package (0) | 2021.10.31 |
[Python #5] Dictionary, Set, Collection (0) | 2021.10.10 |
[Python #4] File (0) | 2021.10.07 |