Ver.0.1 : 20220517 - 상렬

Requests 모듈 기반 지식인 크롤링에 대한것

import requests
import pandas as pd
from tqdm import tqdm
from bs4 import BeautifulSoup
#import ssl

'''
url -> 지식인 특정 카테고리에 Q&A를 긁는 기본 base url이다. 적어도 질문에 대한 답변이 하나는 존재한다
Q&A >교육,학문 > 중학교교육 > 사회  : 110302

'''
def crawl_kin(page_n:int, category_num:int):
    '''
    기본적으로 게시판에는 20개의 게시글이 있고 총 긁어올 정보는 20 x page_n만큼의 QA 정보입니다.
    category는 지식인의 어느 보드를 긁어올것인가에 대한 인자입니다.
    '''
    idx = 0
    accepta = None
    web_df = pd.DataFrame(columns=('category', 'question', 'answer_1', 'answer_2', 'answer_3', 'accept'))
    detail_url = '<https://kin.naver.com/qna/detail.naver?'>
    
    try:
        for page in tqdm(range(1, page_n+1)):
            web_df_column = []

            url = f'<https://kin.naver.com/qna/kinupList.naver?dirId={category_num}&page={page}>'
            
            response = requests.get(url)
            if response.status_code == 200:
                for id in range(1,21):
                    #한 게시판에 게시글이 20개씩있고 이것을 pagenation에 대해서 옮겨가야함
                    html = response.text
                    soup = BeautifulSoup(html, 'html.parser')
                    ul = soup.find('tbody', id='au_board_list')
                    titles = ul.select(f'tr:nth-child({id}) > td.title > a')
                    category = ul.select(f'#au_board_list > tr:nth-child({id}) > td.field > a')[0].text

                    for a in titles:

                        href = detail_url + a.get('href').split('?')[1]
                        detail = requests.get(href)
                        detail_html = detail.text
                        detail_soup = BeautifulSoup(detail_html, 'html.parser')
                        detail_title = detail_soup.find('div', "c-heading__content")
                        
                        if detail_title != None:
                            detail_title = detail_title.text.strip()
                        else:
                            detail_title = "NaN"
                        #content > div.question-content > div > div.c-heading._questionContentsArea.c-heading--default-old > div.c-heading__title > div > div

                        detail_content = detail_soup.find('div', "answer-content__list _answerList")
                        
                        web_df_column = [category, detail_title]
                        for x in range(1,4):
                            answers = None
                            try:
                                answers = detail_content.select_one(f'#answer_{x} > div._endContents.c-heading-answer__content > div._endContentsText.c-heading-answer__content-user')
                                accept = detail_content.select_one(f'#answer_{x} > div.c-heading-answer > div.c-heading-answer__body > div.adopt-check-box > span')
                                if answers != None:
                                    web_df_column.append(answers.text.strip())
                                else:
                                    web_df_column.append("NaN")
                                
                                if accept != None:
                                    accepta = x
                            except:
                                pass

                        web_df_column.append(accepta)
                    
                        web_df.loc[idx] = web_df_column
                        idx += 1

            else :
                print(response.status_code)
                print(page)
                break
    except:
        pass

    web_df.to_csv(f"./{page_n * 20}_{category_num}.csv", index=False)

crawl_kin(100, 110302)

Untitled

예시)

20_사회.csv

2000_110302.csv

<aside> 💡 Q. 사회.csv 를 봤는데 NaN과 11같은 값이 있습니다..! 혹시 이건 어떤 것일까요? 또한, 생각해보니 정말 만일의 상황을 생각해서 해당 질문 링크도 meta 데이터로 들어오면 좋겠단 생각이 들었습니다! @seyeon park

</aside>

<aside> 💡 Q. 지식인이 Title-본문 내용-답변 pair로 이루어져 있는데요, Title에서 질문 내용을 전부 쓰고 본문 내용을 쓰지 않아서 현재 본문 내용에서 뽑아오고 있는 Qustion이 NaN으로 뜨는 경우가 과학 카테고리에서는 많이 존재합니다. Title+본문 내용을 묶어 Qustion으로 함께 쓰는 방법을 제안합니다. @Sangryul Kim

</aside>

A) 아 다른 분야에서는 그문제가 두드러지는군요. 네네 그 부분을 하면 좋을것 같습니다.

<aside> 💡 코드상에서 채택(accept)된 문서가 없을 경우, 제대로 초기화 되지 않아 이전에 채택된 문서 index를 참고하는 문제를 수정해두었습니다. 업데이트된 코드를 사용하시면 좋을 것 같습니다.(데이터 → 지식인 크롤링 - 과학 과목) @Sangryul Kim

</aside>

A) 오류 수정 감사합니다!! 🙂아직 저희가 프로젝트 github를 슬랙에서 이후에 논의하기로 한것 같은데 버전별 관리를 github 설정 이후에 바로 들어가고, 또 코드부분에 대해서도 기존 ipynb파일에 대해서 오류 부분 수정하고 또 어느정도 pilot 끝났으면 .py 형태로 코드 관리를 하는것도 좋아보입니다. @seyeon park

A) .py 형태로 추가해두겠습니다.

환경

python 3.8.13

Ubuntu

beautifulsoup4==4.11.1 requests==2.27.1

pandas == 1.4.2