AI SCHOOL/Python

[Python] 대통령연설기록 수집 - 1

moru_xz 2023. 1. 17. 00:20

연설문 목록 스크래핑

  1. 수집하고자 하는 대상의 URL 을 알아봅니다.
  2. 사이트에 접속한다. => HTTP 요청을 보냅니다. requests
  3. 목록을 받아온다. (번호, 대통령, 형태, 유형, 제목, 연설일자) + BautifulSoup을 통해 내용의 링크도 함께 수집
  4. 3번을 반복해서 전체 데이터를 수집한다.
  5. 파일로 저장한다.

연설문 목록에 URL 추가

  1. 0105에서 저장한 대통령 연설문 목록을 가져옵니다.
  2. 내용링크를 통해 각 연설문의 내용 링크에 요청을 보냅니다.
  3. BeautifulSoup을 통해 내용을 찾아옵니다.
  4. 내용의 링크를 통해 내용을 찾는 함수를 만듭니다.
  5. 전체 게시물에 내용을 찾는 함수를 적용합니다. => 반복문을 사용하지 않고 Pandas 의 map, apply 등의 기능을 사용할 예정입니다.
  6. 수집이 되면 내용 파생변수를 생성해 줍니다.
  7. 저장합니다.
# requests, bs4, pandas 불러오기
import requests
from bs4 import BeautifulSoup as bs
import pandas as pd

table 형식이니까 pd.read_html 해볼까? -> 오류 생김 

why? 인증서 오류가 남 + post 방식 

 

대통 기록관 수집은 이전 수집했던 네이버 금융 뉴스와 일별 시세 어떤 차이 있을까?

- 대통령 기록관은 post방식 -> 바로 requests 보내면 응답 x

- ssl 인증서 사용하고 있음 -> ssl 오류가 남 -> verify = False 해서 해결

만들고 싶은 파일 모양

headers = {"User-Agent": "",
          "Referer": "",
          "Content-Type": "",}
headers  # 왜 안 넣는거지?

이번에는 headers 필요 x 

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

얘도 하는데 인증서가 없는 사이트에서 접속시에 에러메시지가 발생 -> verify = False는 인증서 확인 과정을 생략하겠다는 의미인데 인증서가 없는 사이트 접속으로 인해 혹시라도 발생할 수 있는 문제를 알려주기 위한 경고 메시지 -> 이 경고 메시지 보기 싫으면 비활성화 하려고 사용하는 코드 

 

# 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&searchStartDate=&searchEndDate=&pageUnit=20"
response = requests.post(url, params = params, verify = False)

이 페이지는 페이지 넘어갈 때 마다 url이 변하지 않음 페이지 넘기는 것을 params 지정해서  나타내야 함

여기서 찾을 수 있음 

 

pd.read_html(response.text)[0]

pd.read_html(response.text) 하는 이유는? bs 안 하고 그냥 정말 너무 많고 헷갈려서 바로 pd로

 

 

마지막 페이지 찾기 -> BeautifulSoup  사용 

bs 사용하는 이유는 조금더 깔끔하게 보기 위해서

 

html = bs(response.text)  # 어떤 페이지가 마지막 페이지인지 찾기 위해 

# find_all 로 찾기
html.find_all('a', {'class' : 'last'})[0]['href'].split('=')[-1]

# select 로 찾기 a 넣는 이유는 href가 a 태그의 속성이라
last_page = html.select('nav.board-paging > ul > li > a')[-1]['href'].split('=')[-1]
last_page = int(last_page)
last_page

이런 방식으로 마지막 페이지 찾으면 반복문 작성할 때 마지막 페이지까지 반복할 수 있도록 작성할 수 있음

frm > nav.board-paging.space5 > ul > li:nth-child(14) > a 찾는 방법은 마지막 페이지 누르고 검사 -> select copy

 

df = pd.read_html(response.text)
df #리스트 형식으로

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

df로 만들어줌

 

여기까지 대통령 연설문 목록 가져오는 방법

 

연설문 목록에 URL 추가

  1. 0105에서 저장한 대통령 연설문 목록을 가져옵니다.
  2. 내용링크를 통해 각 연설문의 내용 링크에 요청을 보냅니다.
  3. BeautifulSoup을 통해 내용을 찾아옵니다.
  4. 내용의 링크를 통해 내용을 찾는 함수를 만듭니다.
  5. 전체 게시물에 내용을 찾는 함수를 적용합니다. => 반복문을 사용하지 않고 Pandas 의 map, apply 등의 기능을 사용할 예정입니다.
  6. 수집이 되면 내용 파생변수를 생성해 줍니다.
  7. 저장합니다.

내용링크를 찾는 방법

내용 검사 -> 네트워크 -> a태그 통해 링크 알 수 있음 (어떻게 생겼나 알 수 있음)

그 다음 할 일은? selector로 복사 -> bs로 select, find, find_all 사용해서 a태그 찾기

 

selector copy로 알아낸 것

#M_More > tr:nth-child(5) > td.subject > a
-> 그런데 (5) 이렇게 넣어주면 전체 찾을 수 없고 5번째 것만 찾게 됨 
html = bs(response.text) 

# .select() 로 해당 a 태그 찾기 
html.select('#M_More > tr > td.subject > a')

html.find_all('td', {'class' : 'subject'})

이 방법도 있음

 

a tag 찾기

# a tag 찾기
print(html.select('#M_More > tr > td.subject > a')[0]['href'])
print(html.select('#M_More > tr > td.subject > a')[1]['href'])

href list 만들기

정말 리스트에 담기 위한 과정임

a_href = []

for i in html.select('#M_More > tr > td.subject > a') :
     a_href.append(i['href'])#href하면 링크만 뽑아올 수 있음

a_href

# 방법 2
a_href = []
for i in range(len(html.select('#M_More > tr > td.subject > a'))) :
    a_href.append(html.select('#M_More > tr > td.subject > a')[i]['href'])

a_href

# 방법 3
a_href = []

for i, val in enumerate(html.select('#M_More > tr > td.subject > a')) :
    a_href.append(val['href'])

a_href

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

a_href

 

내용링크 파생변수 만들기

# "내용링크" 파생변수 만들기
df["내용링크"] = a_href
df.head(2)

 

전체 과정 함수로

 

def page_scrapping(page_no):
    """
    1) page 번호로 URL 만들기
    2) requests.post()로 요청하기
    3) bs 적용
    4) 테이블 찾기
    5) a 태그 목록 찾기
    6) 내용링크에 a 태그 주소 추가하기
    7) 데이터프레임 반환
    """
    url = "https://www.pa.go.kr/research/contents/speech/index.jsp?"
    params = f"spMode=&artid=&catid=&pageIndex={page_no}&searchHistoryCount=0&pageUnit=20"

    response = requests.post(url=url, params=params, verify=False)
    html = bs(response.text)
    df_table = pd.read_html(response.text)[0]
    df_table["내용링크"] = [ a["href"] for a in html.select("#M_More > tr > td.subject > a") ]
    
    return df_table
# 함수가 잘 동작하는지 확인
page_scrapping(page_no=3)

# 함수 잘 작동하는지 확인 2
i = 3
print(df_table["제목"][i])
print(url + df_table["내용링크"][i])

 

마지막 페이지까지 연설 목록 가져오고 링크까지!

from tqdm import trange
import time

# 경고메시지가 있으면 tqdm 로그가 너무 많이 찍히기 때문에 경고메시지를 제거합니다.
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

page_list = []
for page_no in trange(1, last_page + 1) :
    result = page_scrapping(page_no)
    page_list.append(result)
    time.sleep(0.001)
    
pd.concat(page_list)