Today I Learned

[TIL] 네이버 종목토론실 스크래핑

by Holly Yoon

TIL

필요한 라이브러리 불러오기

# requests, bs4, pandas 불러오기
import requests
from bs4 import BeautifulSoup as bs
import pandas as pd

네이버 종목토론실에서 게시글의 정보(제목, 링크)를 불러오기

  • board_url : 종목토론실의 url은 code_no, page_no으로 구성되어있으며, 해당 정보는 pagination을 클릭하여 network탭에서 확인할 수 있다.
  • str.replace() : 게시글의 url을 수집하기 위해서 a태그의 title attribute를 이용하려고 합니다. 이를 위해서는 제목 상의 '[덧글갯수]' 해당 부분을 삭제해주어야한다. 정규식을 사용한다 (\s* : space 존재 \d+ : 여러개의 숫자가 옴)
  • find_all('a', {'title':title}) : 제목과 같은 title태그를 가지고 있는 a태그를 찾는다.
  • table['제목'].items() : '제목' row를 시리즈로 만들어서 idx값과 매칭시켜 새로운 열을 만든다.
def get_board_list(code_no, page_no):
    """
    page_no별 게시판 글 수집
    """ 
    # 1) URL 을 만들기
    board_url = f"https://finance.naver.com/item/board.naver?code={code_no}&page={page_no}"
    # 2) requests 로 요청하기
    headers = {"user-agent": "Mozilla/5.0"}
    response = requests.get(board_url, headers=headers)
    # 3) pd.read_html(response.text) 로 데이터프레임 만들기
    table = pd.read_html(response.text)[1]
    # 4) 결측치 제거하기
    table = table.drop("Unnamed: 6", axis = 1)
    table = table.dropna()
    table = table.drop_duplicates()
    # 5) 제목에서 덧글 갯수 빼기
    table['제목'] = table["제목"].str.replace(r'\s*\[\d+\]', '')
    # 6) link 더하기
    html=bs(response.text)
    for idx, title in table['제목'].items():
        page_link = html.find_all("a", {"title":title})
        if page_link:
            table.loc[idx,'링크']="https://finance.naver.com"+page_link[0]['href']
    # 7) 본문 더하기
    for idx, link in table['링크'].items():
        table.loc[idx, '게시물']=add_article(link)
    # 8) 데이터프레임 반환하기
    return table

게시물 본문 내용을 가져오기

  • pd.isna() : 링크가 있을 경우, 게시물 내용을 가져오도록 만든다.
  • text.strip() : 게시물 내용을 한 줄에 오도록 묶어준다.
def add_article(link):
    if pd.isna(link) == False:
        headers = {"user-agent": "Mozilla/5.0"}
        response = requests.get(link, headers=headers)
        soup = bs(response.text,'html.parser')
        divs = soup.find_all("div", class_="view_se")
        if divs:
            return divs[0].text.strip()
    else:
        return None

여러 페이지의 게시글 수집하기

  • pagination을 따라 수집되도록 for문으로 작성해준다.
  • pd.concat() : 수집된 리스트를 하나의 dataframe으로 묶어준다.
  • reset_index(drop=True) : index는 리셋하여 새롭게 생성한다.
def get_board_all(code_no, page_no):
    """
    page_no까지 게시판 글 수집
    """
    tables=[]
    for i in range(page_no):
        table=get_board_list(code_no, page_no)
        tables.append(table)        
        i += 1
    
    tables = pd.concat(tables)
    tables = tables.reset_index(drop=True)
    return tables

 

***

하루종일 걸린 과제 완료! what I learned : 링크가 없는 게시물에 대한 예외처리, 자료형을 고려해서 코드를 작성해야하는 부분이 헷갈림 (index랑 매칭해서 넣어주는 부분), 효율적인 코드를 짜고 싶은데.. 일단 동작하는 코드를 짜는데서 그쳤습니다...

'TIL' 카테고리의 다른 글

대용량 파일 관리 - parquet, downcast  (0) 2023.02.27
[TIL] 내용수집 함수만들기 (pandas)  (0) 2023.01.19
[TIL] 스크랩핑 with Pandas  (0) 2023.01.12
[TIL] Pandas 시작하기  (0) 2023.01.10
[TIL] 파이썬 기초 수업 끝 -  (0) 2023.01.06

블로그의 정보

Study Log by Holly

Holly Yoon

활동하기