[Data] 웹 크롤링 기법 정리

서효정·2022년 12월 4일
0

Data

목록 보기
5/5
post-thumbnail

📖 API 용어 정리

  • API (Application Programming Interface) : 특정 프로그램을 만들기 위해 제공되는 모듈

  • Open API : 누구나 사용할 수 있도록 공개된 API

  • Rest API (Representational State Transfer) : HTTP 프로토콜을 통해 서버 제공 기능을 사용할 수 있는 함수


📖 JSON 용어 정리

  • JSON (JavaScript Object Notation)

  • 서버와 클라이언트, 혹은 컴퓨터와 프로그램 사이에 데이터를 주고받을 때 사용하는 데이터 포맷

  • 키와 값을 괄호나 세미콜론을 활용하여 간단하게 표현할 수 있으며, 언어나 운영체제에 구애받지 않기 때문에 널리 활용됨

  • {"id" : "01", "language" : "Java", "edition" : "third"}


📖 Open API 크롤링 기법 정리

1-1. urllib 라이브러리

  • urllib.request는 URL(Uniform Resource Locator)을 가져오기 위한 파이썬 모듈

  • urllib.request는 관련 네트워크 프로토콜을 사용하여 많은 URL 스킴(scheme)에 대해 URL을 가져오는 것을 지원합니다.

	- 네트워크 프로토콜 : ex. FTP, HTTP
	- URL 스킴 : URL에서 ":" 앞의 문자열 
      ex. "ftp"는 "ftp://python.org/"의 URL 스킴
      

1-2. urllib 라이브러리 크롤링 코드 (네이버 open API 예제)

# 블로그 검색
import os
import sys
import urllib.request
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
encText = urllib.parse.quote("검색할 단어")
url = "https://openapi.naver.com/v1/search/blog?query=" + encText # json 결과
# url = "https://openapi.naver.com/v1/search/blog.xml?query=" + encText # xml 결과
request = urllib.request.Request(url)
request.add_header("X-Naver-Client-Id",client_id)
request.add_header("X-Naver-Client-Secret",client_secret)
response = urllib.request.urlopen(request)
rescode = response.getcode()
if(rescode==200):
    response_body = response.read()
    print(response_body.decode('utf-8'))
else:
    print("Error Code:" + rescode)

2-1. requests 라이브러리

  • 파이썬으로 HTTP 통신이 필요한 프로그램을 작성할 때 가장 많이 사용되는 라이브러리로, 원격에 있는 API를 호출할 때 유용하게 사용할 수 있음

  • HTTP 요청 방식(method)
    - GET 방식: requests.get()
    - POST 방식: requests.post()
    - PUT 방식: requests.put()
    - DELETE 방식: requests.delete()

  • 응답상태
    - response.status_code를 사용해서 확인 가능
    - 다양한 응답상태 참고 블로그

>>> response = requests.get("https://jsonplaceholder.typicode.com/users/1")
>>> response.status_code
200 # 클라이언트의 요청을 서버가 정상적으로 처리했다.
>>> response = requests.get("https://jsonplaceholder.typicode.com/users/100")
>>> response.status_code
404 # 클라이언트가 요청한 자원이 존재하지 않다.
>>> response = requests.post("https://jsonplaceholder.typicode.com/users")
>>> response.status_code
201 # 클라이언트의 요청을 서버가 정상적으로 처리했고 새로운 리소스가 생겼다.
  • 응답전문
    - 요청이 정상적으로 처리가 된 경우, 응답 전문(response - body/payload)에 요청한 데이터가 담겨져 옴
    - 응답 전문은 크게 3가지 방식으로 읽어올 수 있음
>>> response = requests.get("https://jsonplaceholder.typicode.com/users/1")
1) content 속성을 통해 바이너리 원문을 얻기
>>> response.contentb'{\n  "id": 1,\n  "name": "Leanne Graham",\n  "username": "Bret",\n  "email": "Sincere@april.biz",\n  "address": {\n    "street": "Kulas Light",\n    "suite": "Apt. 556",\n    "city": "Gwenborough",\n    "zipcode": "92998-3874",\n    "geo": {\n      "lat": "-37.3159",\n      "lng": "81.1496"\n    }\n  },\n  "phone": "1-770-736-8031 x56442",\n  "website": "hildegard.org",\n  "company": {\n    "name": "Romaguera-Crona",\n    "catchPhrase": "Multi-layered client-server neural-net",\n    "bs": "harness real-time e-markets"\n  }\n}'
1) text 속성을 통해 UTF-8로 인코딩된 문자열을 얻기
>>> response.text
'{\n  "id": 1,\n  "name": "Leanne Graham",\n  "username": "Bret",\n  "email": "Sincere@april.biz",\n  "address": {\n    "street": "Kulas Light",\n    "suite": "Apt. 556",\n    "city": "Gwenborough",\n    "zipcode": "92998-3874",\n    "geo": {\n      "lat": "-37.3159",\n      "lng": "81.1496"\n    }\n  },\n  "phone": "1-770-736-8031 x56442",\n  "website": "hildegard.org",\n  "company": {\n    "name": "Romaguera-Crona",\n    "catchPhrase": "Multi-layered client-server neural-net",\n    "bs": "harness real-time e-markets"\n  }\n}'
3) json() 함수를 통해 사전(dictionary) 객체 얻기
>>> response.json()
{'id': 1, 'name': 'Leanne Graham', 'username': 'Bret', 'email': 'Sincere@april.biz', 'address': {'street': 'Kulas Light', 'suite': 'Apt. 556', 'city': 'Gwenborough', 'zipcode': '92998-3874', 'geo': {'lat': '-37.3159', 'lng': '81.1496'}}, 'phone': '1-770-736-8031 x56442', 'website': 'hildegard.org', 'company': {'name': 'Romaguera-Crona', 'catchPhrase': 'Multi-layered client-server neural-net', 'bs': 'harness real-time e-markets'}}
  • 응답헤더
    - 응답에 대한 메타 데이터를 담고 있음
    - headers 속성을 통해 사전의 형태로 얻을 수 있음
	>>> response = requests.get("https://jsonplaceholder.typicode.com/users/1")
	>>> response.headers
    {'Date': 'Sat, 12 Dec 2020 21:10:49 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Set-Cookie': '__cfduid=d92df672c0d58b06b245dd0b8d317e2141607807449; expires=Mon, 11-Jan-21 21:10:49 GMT; path=/; domain=.typicode.com; HttpOnly; SameSite=Lax', 'X-Powered-By': 'Express', 'X-Ratelimit-Limit': '1000', 'X-Ratelimit-Remaining': '999', 'X-Ratelimit-Reset': '1607798104', 'Vary': 'Origin, Accept-Encoding', 'Access-Control-Allow-Credentials': 'true', 'Cache-Control': 'max-age=43200', 'Pragma': 'no-cache', 'Expires': '-1', 'X-Content-Type-Options': 'nosniff', 'Etag': 'W/"1fd-+2Y3G3w049iSZtw5t1mzSnunngE"', 'Via': '1.1 vegur', 'CF-Cache-Status': 'HIT', 'Age': '9352', 'cf-request-id': '06fa63d142000038668b9a7000000001', 'Expect-CT': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"', 'Report-To': '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=Vk2e8Q%2FBK4wOSQc12Cgs0nqvZHpyUb4c0o%2BWCgLzwdqPLQM2HJ5hNHW%2Fmc8fNr73wqQ2LrzEdScfv5bejTYVrXRlUfAyPcGnv1me%2BHlZKc7IKKOi%2BO%2ButGVrdkWS"}],"group":"cf-nel","max_age":604800}', 'NEL': '{"report_to":"cf-nel","max_age":604800}', 'Server': 'cloudflare', 'CF-RAY': '600a6f2edfe23866-IAD', 'Content-Encoding': 'gzip'}
	>>> response.headers['Content-Type']
    'application/json; charset=utf-8'
  • 요청쿼리
    - GET 방식으로 HTTP 요청을 할 때는 쿼리 스트링(query string)을 통해 응답받을 데이터를 필터링하는 경우가 많음
    • params 옵션을 사용하면 쿼리 스크링을 사전의 형태로 넘길 수 있음
	# https://jsonplaceholder.typicode.com/posts?userId=1
	>>> response = requests.get("https://jsonplaceholder.typicode.com/posts", params={"userId": "1"})
	>>> [post["id"] for post in response.json()]
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 요청전문
    - POST나 PUT 방식으로 HTTP 요청을 할 때는 보통 요청 전문(request body/payload)에 데이터를 담아서 보냄
    1) data 옵션 사용
    : HTML 양식(form) 포멧의 데이터를 전송할 수 있으며, 이 때 Content-Type 요청 헤더는 application/x-www-form-urlencoded로 자동 설정됨
    >>> requests.post("https://jsonplaceholder.typicode.com/users", data={'name': 'Test User'})
    <Response [201]>







profile
Data Analyst

0개의 댓글