Molybdenum의 개발기록

[TIL] 14-16일차_President_Speech_Crawling 본문

TIL

[TIL] 14-16일차_President_Speech_Crawling

Molybdenum_j 2023. 3. 6. 16:35

▶ 대통령 연설문 목록크롤링

역대 대통령들의 연설문 목록을 크롤링해보려고 한다.

 

 

1) 라이브러리 로드

import requests
from bs4 import BeautifulSoup as bs
import pandas as pd

사용할 라이브러리는 request,  pandas, beatuifulsoup을 사용할 예정이다.

 

2)  수집할 대상의 url을 수집

page_no = 70

url = "https://www.pa.go.kr/research/contents/speech/index.jsp"
params = f"spMode=&artid=&catid=&pageIndex={page_no}&searchHistoryCount=0&pageUnit=20"

headers 정보를 확인한다.

headers = {"User-Agent": "",
          "Referer": "",
          "Content-Type": "",}

 

3) 사이트에 접속하여 HTTP 요청을 보낸다 => requests

인증서가 없는 사이트는 접속 시 웹 브라우저에서 다음과 같은 에러가 발생한다.

이 때 verify=False를 통해 SSL 인증서 확인 과정을 생략하겠다는 의미로 인증서가 없는 사이트 접속으로 인해 혹시라도 발생할 수 있는 문제를 알려주기 위한 경고 메시지 이다.  인증서 오류가 신경 쓰인다면 아래 경고메시지 비활성화 처리로 없앨 수 있지만 경고이기 때문에 데이터 수집에는 문제가 없다.

requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

response = requests.post(url, params=params, verify=False)

 

 

4) 목록을 받아온다. (번호, 대통령, 형태, 유형, 제목, 연설일자) + BeautifulSoup을 통해 내용의 링크 주소도 함께 수집

 

html = bs(response.text)

 

5) 마지막 페이지 번호 찾기

find_all = 반복문을 작성할 때 마지막 페이지 까지 반복하도록 작성할 수 있다.

html.find_all("a", {"class": "last"})[0]["href"].split("=")[-1]

last_page = html.select("nav.board-paging.space5 > ul > li > a")[-1]["href"].split("=")[-1]
last_page = int(last_page)

=> 449

 

6) 데이터 프레임으로 변환한다.

df = pd.read_html(response.text)[0]

 

7) 내용 링크 경로를 찾는다.

  • select()를 사용한 경우
html.select("#M_More > tr > td.subject > a")

 

  • find_all 을 사용한 경우
html.find_all("td", {"class": "subject"})

 

8) 3번을 반복해서 전체 데이터를 수집한다.

상세 정보를 위한 링크정보를 수집한다.

  • a tag를 찾는다.
html.select("#M_More > tr > td.subject > a")[0]["href"]

 

  • href list 만든다.
    • for~in html.select 사용
a_href = []
for a in html.select("#M_More > tr > td.subject > a"):
    a_href.append(a["href"])

 

  • for~ in range(len()) 사용
a_href = []
for i, val in enumerate(html.select("#M_More > tr > td.subject > a")):
        a_href.append(val["href"])

 

  • 리스트 컴프리헨션(리스트 함축)
a_href = [ a["href"] for a in html.select("#M_More > tr > td.subject > a") ]

 

  • "내용링크" 파생 변수를 만든다
df["내용링크"] = a_href

 


 

▶ 함수를 만든다.

def page_scrapping(page_no):
# 1. page 번호로 URL 만들기
    url = "https://www.pa.go.kr/research/contents/speech/index.jsp?"
    params = f"spMode=&artid=&catid=&pageIndex={page_no}&searchHistoryCount=0&pageUnit=20"
# 2. requests.post()로 요청하기
    response = requests.post(url=url, params=params, verify=False)
# 3. bs 적용하기
    html = bs(response.text)
# 4. 테이블 찾기
    table = pd.read_html(response.text)[0]
# 5. a태그 목록 찾기
# 6. 내용링크에 a태그 주소 추가하기
    table["내용링크"] = [ a["href"] for a in html.select("#M_More > tr > td.subject > a") ]
# 7. 데이터 프레임 반환   
    return table

 

함수가 잘 동작하는지를 확인한다

result = page_scrapping(page_no=100)
display(result)

수집한 내용의 제목과 링크가 맞는지 확인한다.

i = 5
print(result["제목"][i])
print(url + result["내용링크"][i])

 

전체 데이터 수집

from tqdm import trange
import time

page_list = []
for page_no in range(1,last_page+1):
    result = page_scrapping(page_no)
    page_list.append(result)
    time.sleep(0.01)

 

 

9) 파일로 저장한다.

수집한 데이터를 하나의 데이터 프레임으로 합친다

df = pd.concat(page_list)

csv 파일로 저장한다

file_name = "대통령연설기록.csv"
df.to_csv(file_name, index=False)

csv 파일 읽어오기

pd.read_csv(file_name)

 


 

▶ 대통령 연설문 내용크롤링

목록에 대한 크롤링이 끝났으니 연설문 내용을 크롤링 해본다

 

1) 수집한 연설목록을 가져온다

df = pd.read_csv('/content/대통령연설기록.csv')

 

  • head() / tail() = 가장 앞 쪽줄과 가장 뒤 쪽 줄을 출력해보여준다.
display(df.head(5))
df.tail(5)

 

 

2) URL을 만든다.

base_url = "https://www.pa.go.kr/research/contents/speech/index.jsp"
sub_url = df.iloc[0]["내용링크"]
print(df.iloc[-2]["제목"])
print(base_url + sub_url)

 

3) 내용 페이지에 HTTP를 요청한다

response = requests.post(base_url + sub_url, verify=False)
print(response.text)

 

4) BeautifulSoup을 적용한다

html = bs(response.text)

 

5) 내용을 수집한다

  • select()를 이용한 방법
content = html.select("#content > div > table > tbody > tr > td.content")[0].text

 

  • find() 를 이용한 방법
content = html.find("td",{"class":"content"}).text

 

  • find_all을 이용한 방법
content = html.find_all("td",{"class":"contetnt"})

 

▶ 함수로 만든다

def get_content(sub_url):

    try:
# 1. 수집할 URL 만든다
        base_url = "https://www.pa.go.kr/research/contents/speech/index.jsp"
        url = base_url + sub_url
# 2. requests로 HTTP요청한다
        response = response.get(url, verify=False)
# 3. response.text에 BeautifulSoup 적용한다
        html = bs(response.text)
# 4. 내용 가져온다
        content = html.select("td.content")[0].text
# 5. time.sleep() 사용
        time.slpee(0.01)
# 6. 내용반환한다
        return content

    except:

        return None

 

  • except: HTTPConnection :

= 특정 시간을 쉬었다가 해당 함수를 다시 호출하게 할 수도 있습니다.

HTTPConnection오류일때만 해당 함수를 다시 호출하게 하는 방법도 있다.

time.sleep(60)

get_content(sub_url)

  • 중간에 오류가 나게 되면 다시 처음부터 수집해야 하는 상황이 될 수도 있기 때문에 일단 오류가 나면 NA값을 반환하도록 한다.

함수가 잘 만들어졌는지 확인한다

href = df.iloc[3]["내용링크"]
get_content(href)

 

6) 전체 데이터에 적용한다

from tqdm.notebook import tqdm
tqdm.pandas()

df = df.head(10)

view = df["내용링크"].progress_map(get_content)
view

pandas는 함수를 반복해서 적용해야 할 때 map, apply, applymap을 사용한다. 진행상태를 알기 위해서는 tqdm의 progress_map, progress_apply를 사용한다.

=> tqdm 사용시 결과는 이렇게 나온다.

 

7) "내용" 변수를 만든다

df["내용"] = view

내용 변수가 추가되었다.

 

8) 파일로 저장한다.

file_name = "대통령연설문내용.csv"
df.to_csv(file_name,index=False)
pd.read_csv(file_name)

 

Comments