[PYTHON] 스크랩핑 실습-2

보안 잃기·2023년 9월 18일

Python

목록 보기
3/3

지난 이야기

  • 지난 실습에는 정보를 하나하나 찾아가는 방법을 익혔었다.
  • 오늘은 찾은 모든 정보를 가지고 가공하여 json 형태로 저장하는 방법을 배워보자.

table의 형태

  • 오늘 실습을 하기 위해선 table의 형태를 우선 알아야 한다.
  • 지난 번에도 얘기했지만 table 안에는 thead(각 열의 제목)과 tbody(각 열의 내용)으로 나뉜다.
  • tbody 안에는 하나의 행인 tr과 그 안에 셀 형태로 td가 있다.
  • 아래 이미지를 참고하자.

복습

.find("tr")

import requests
from bs4 import BeautifulSoup

req = requests.get('https://www.krcert.or.kr/kr/bbs/list.do?bbsId=B0000302&menuNo=205023')
scrap = BeautifulSoup(req.content, 'html.parser')

table = scrap.find('table')
tbody = table.find('tbody')
trs = tbody.find('tr')

tds = trs.find_all('td')
num = tds[0].text
title = tds[1].text
title2 = title.replace("\n", "")
severity = tds[2].text
cvss = tds[3].text
vuln_dic = {'num':num, 'title':title2, 'severity':severity, 'cvss':cvss}

print(vuln_dic)
  • 지난번 실습에서는 tr의 1개를 찾는 연습을 했지만 이번엔 모든 tr을 찾아 그 안의 td 내용들을 하나의 리스트형태로 저장하려고 한다.

실습

1. 모든 tr 찾기

  • 지난번과의 다른 점은 tr을 find가 아닌 find_all로 찾는 것이다.
trs = tbody.find_all("tr")

  • 모든 tr 안의 내용을 구분자(,)로 하여 리스트 형태로 가져오는 것을 볼 수 있다.
  • <td> 내용 </td> 하나가 첫번째 내용이다.

2. 각 tr에 td들을 dictionary 형태로 저장

  • 각 tr 들 안에도 <td>가 여러개이고 이를 find_all로 찾아 필요한 내용만 추출할 수 있다.
  • 동작 방식(로직)은 다음과 같다.
  • 우리는 for 문을 이용하여 각 tr의 td 내용들을 추출할 것이다.
  • 참고로 for 문은 다음과 같은 형태로 파이썬 리스트에서 사용한다.

3. for tr in trs:

  • for 문을 이용하여 tr의 각 <td>들을 리스트 순서대로 추출할 것이다.
for tr in trs:
	tds = tr.find_all("td")

  • 위처럼 각 td들이 리스트형태로 분리된 것을 볼 수 있다.
  • html태그는 필요하지 않으니 .text를 이용하여 내용만 가져와보자
    num = tds[0].text
    title = tds[1].text
    severity = tds[2].text
    cvss = tds[3].text
  • 각 리스트의 index를 보고 필요한 정보만 가져온 것이다.

4. dictionary 형태로 정보 저장

dic = {'num':num, 'title':title, 'severity':severity, 'cvss':cvss}
  • dictionary, 즉, 사전 형태로 출력할 수 있도록 함수를 작성했다.

    dictionary는 key:value 형태로 "A는 B다"라고 생각하면 된다.

  • 사전 형태로 가져오니 title에 \r, \n과 같은 개행문자가 보인다.
  • 개행문자는 replace를 이용하여 없앨 수 있다.
retitle = title.replace("\r", "").replace("\t", "").replace("\n", "")
  • replace 문법은 ("A", "B"), A를 B로 대체(변경)하는 문법이다.
  • 변경한 title 변수인 retitle을 'title': retitle로 변경해보자

여기까지 왔다면 거의 다 끝났다고 볼 수 있다.

  • 우리는 이제 하나의 리스트 1번을 완성했으니 나머지 tr행들의 정보도 가져와보자.
  • 그러기 전에 빼먹은 게 하나 있다.
  • 위의 1개 정보를 리스트에 저장을 해야하는데 저장할 변수를 지정하지 않았다.
  • 리스트 타입의 변수 하나를 for문 전에 하나 만들어서 for문 마지막에 해당 정보를 하나씩 넣어보자.

5. list 정보 삽입

  • list에 정보를 추가하기 위해선 우리는 append 라는 것을 사용한다.
  • 리스트 타입의 변수 하나를 먼저 지정하자.
vuln = []
  • 그리고 위에 for문에서 하나의 정보가 만들어질 때마다 리스트에 저장하려면,,
vuln.append(dic)

vuln 변수는 꼭 for 문 전에 지정해줘야 한다. for문 안에 vuln 변수가 있다면 계속해서 리셋되어 마지막 정보만 vuln 변수에 저장될 것이다.

6. for문 완성

vuln = []

for tr in trs:
    tds = tr.find_all("td")
    num = tds[0].text
    title = tds[1].text
    retitle = title.replace("\r", "").replace("\t", "").replace("\n", "")
    severity = tds[2].text
    cvss = tds[3].text
    dic = {'num':num, 'title':retitle, 'severity':severity, 'cvss':cvss}
    vuln.append(dic)
  • 출력해보자
  • 위처럼 한 웹페이지 안에 모든 정보를 가져왔다.

7. json 형태로 만들기

  • json 형태로 만들기 위해선 json 모듈을 삽입하여 json.dump(s)를 사용하면 된다.
  • 메모리(일시적)형태로 json 형식으로 잘 만들어졌는지 확인해보자.
jsondump = json.dumps(vuln, indent=4)
print(jsondump)
  • jsondump라는 변수를 만들고 json.dumps(vuln(변수), indent(들여쓰기)=4)로 지정하고 출력해보면,,

    indent는 보통 4를 이용한다. 구분자(,)에 따라 줄바꿈을 해주어 이쁘게 작성된다.

  • 위와 같이 잘 만들어진 것을 볼 수 있다.

8. json 저장

  • json을 저장하려면 우선은 json을 open 함수로 w(write:쓰기), 그리고 encoding을 지정하여 열어준다.
with open('vuln.json', "w", encoding="utf-8") as make_file:

with ~ as 변수: 는 with 하위의 동작이 끝나면 닫는다.

  • json 파일(없을 시 생성됨)을 열어주고 write를 할 준비가 끝났다.
  • 그렇다면 json 파일에 저장할 내용을 적어주자
json.dump(vuln, make_file, ensure_ascii=False, indent=4)
  • json.dump(입력해줄 내용, 어디에 저장할지(변수), 아스키코드 설정, 들여쓰기 지정) 문법 형태
  • ensure_ascii=True일 경우 ascii코드(예: 0x00)가 아닐 경우 이스케이프 문자로 표기된다.

9. 코드 완성

import requests
from bs4 import BeautifulSoup
import json

req = requests.get('https://www.krcert.or.kr/kr/bbs/list.do?bbsId=B0000302&menuNo=205023')
scrap = BeautifulSoup(req.content, 'html.parser')

table = scrap.find('table')
tbody = table.find('tbody')
trs = tbody.find_all('tr')

vuln = []

for tr in trs:
    tds = tr.find_all("td")
    num = tds[0].text
    title = tds[1].text
    retitle = title.replace("\r", "").replace("\t", "").replace("\n", "")
    severity = tds[2].text
    cvss = tds[3].text
    dic = {'num':num, 'title':retitle, 'severity':severity, 'cvss':cvss}
    vuln.append(dic)

with open('vuln.json', "w", encoding="utf-8") as make_file:
    json.dump(vuln, make_file, ensure_ascii=False, indent=4)

10. 저장된 json 파일 확인

결론

  • 본 실습의 경우 한 페이지에서만 스크랩하여 json 형태로 저장하는 법을 다루어보았다.
  • 모든 페이지에서 정보를 가져와 json으로 저장하는 건 각자의 방법으로 직접 시도해보자.
profile
잃기전에 기억하기

0개의 댓글