TIL/멋사_AI스쿨_TIL

221004 AI스쿨 TIL 웹스크래핑

둥둥런 2022. 10. 4. 22:46

오늘의 회고

  • 사실(Fact) : 서울정보소통광장 120 데이터 수집하기 (목록, 내용)
  • 느낌(Feeling) : 이해도가 조금 높아지니까 흥미가 더 생겨서 다른 페이지도 웹스크래핑에 도전해보고 싶어졌다.
  • 교훈(Finding) : 오늘 수업 복습, 과제로 전체 데이터 가져와보는 것을 해봐야겠다.

멋사 AI스쿨 main lecture by 박조은 강사님

 

지난 주 복습

웹스크래핑은 requests로 수집하고 bs로 파싱하고 해석한다고 표현한다.

with 구문은 메모리를 할당 → 파일을 오픈할 때 주로 사용한다

로봇배제 표준 robot.txt

네트워크탭 Headers에서 get인지 post인지 확인 가능

 

프로그램을 구현하기 전에 과정을 정리해보는 단계가 중요하다.

팀플을 할 때도 이런 과정을 미리 공유해보고 시작하면 좋다.

프로그래밍 | 슈도코드 | pseudocode | 의사코드 | 순서도 -> 슈도코드 - RECOR:D

ex) 웹페이지에서 데이터를 가져오는 과정을 예측해보기

  1. 테이블 정보만 포함한 url 링크를 찾아 가져온다
  2. html 테이블태그를 이용해서 목록(번호, 제목, 생산일, 조회수)를 수집한다
  3. 페이지 반복문을 통해 전체 페이지의 목록을 가져온다
  4. href 주소도 담아둔다.
  5. 목록의 href주소의 끝의 8자리 숫자를 상세 페이지 번호로 가져온다
  6. 본문의 문서 정보 테이블도 가져온다.
  7. 상세 페이지 번호를 변수로 이용해서 전체 정보를 가져온다(parameter에 argument 넣는 작업)
  8. 가져온 정보를 목록 + 본문으로 데이터프레임 형태로 연결한다

서울시 다산콜센터 주요민원 정보 웹 스크랩핑

메인 테이블 정보 수집하기

라이브러리 불러오기

import pandas as pd
import numpy as np
from bs4 import BeautifulSoup as bs
import requests
import time

URL 링크의 table 정보 가져오기

# pd.read_html 을 통해 해당 URL의 table 정보를 읽어옵니다.
table = pd.read_html(base_url, encoding = "utf-8") 
# 글자가 꺠지면 encoding 추가 uf-8, cp949 둘 중 하나
table[0]

상세 정보를 수집할때 requests 활용

응답 코드확인: .status_code 200이 나오면 OK

 

특정 페이지 목록을 수집하는 함수로 만들어서 활용

def get_one_page(page_no):
    """
    120 주요질문의 특정 페이지 목록을 수집
    """
    # 1) page_no 마다 url이 변경되게 f-string 을 사용해 만든다.
    base_url = f"<https://opengov.seoul.go.kr/civilappeal/list?items_per_page=50&page={page_no}>"
    # 2) requests 를 사용해서 요청을 보내고 응답을 받는다.
    response = requests.get(base_url)
    # 3) pd.read_html을 사용해서 table tag로 게시물을 읽어온다.
    # 4) 3번 결과에서 0번 인덱스를 가져와 데이터프레임으로 목록의 내용을 만든다.
    table = pd.read_html(response.text)[0]
    # 5) html tag를 parsing할 수 있게 bs 형태로 만든다.
    html = bs(response.text)
    # 6) 목록 안에 있는 a tag를 찾는다.
    a_list = html.select("td.data-title.aLeft > a")
    # 7) a tag 안에서 string 을 분리해서 내용번호만 리스트 형태로 만든다.
    # 8) 4)의 결과에 "내용번호"라는 컬럼을 만들고 a tag의 리스트를 추가한다.
    table["내용번호"] = [a_tag["href"].split("/")[-1] for a_tag in a_list]

    return table

 

try except 구문 → 예외 처리

  • return 안내 문구 또는 raise Exception()으로 오류 발생시키기

 

반복문을 통한 여러 페이지 수집하기

반복을 빠져나가는 조건을 무엇으로 할 것인지 정하는 것이 중요하다.

 

while문 멈추는 조건

return 값의 타입이 str이면 멈추기

 

df_temp.shape[0] == 0로 쓸 수없는 이유는?

attribute error가 발생, 오류 메시지는 str타입

 

# time.sleep을 통해 일정 간격 쉬었다가 가져옵니다.
# 게시물이 없으면 멈춥니다.
page_no = 1
table_list = []

while True:
    print(page_no, end=",")
    df_temp = get_one_page(page_no)
    if type(df_temp) == str : #오류메시지는 str이라서 조건
        print("수집이 완료되었습니다.")
        break
    table_list.append(df_temp)
    page_no += 1
    time.sleep(0.01)

데이터 병합하기 pd.concat(table_list)

파일 저장하기 df.to_csv(file_name, index=False)

 


각 페이지의 상세 정보 수집하기

SELECTOR 사용

html.select("#content > div > div.view-content.view-content-article > div > div.line-all")
#content > div > div.view-content.view-content-article > div:nth-child(2) > div

selector 가져올때 class가 복사가 안되면 .찍고 직접 입력해도된다

 

텍스트만 가져오기

.get_text()

.text

 

2X3 테이블을 1X6으로 펼치는법

1) 전치행렬 활용

2) index맞춤

3) pd.concat활용 axis=1