python/자동화

[Python] 웹크롤링 - 태그를 이용해서 크롤링하기 - (3) 사전을 Json파일로 저장

sillon 2023. 3. 7. 23:26
728x90
반응형

사전으로 저장하고자 하는 내용을 크롤링하면서 오류가 있는 것을 발견했습니다.

 

from bs4 import BeautifulSoup
import urllib.request as req 
import argparse # 특정 웹사이트로 접속하기 위해
import re
from urllib.parse import quote

def crawling_list(url):
    res = req.urlopen(url).read()
    soup = BeautifulSoup(res, 'html.parser') #분석 용이하게 파싱
    find_tag = soup.findAll("a",{"class":"depth1-title"}) # "div",{"class":"section_body"}

    korean_hist = dict()
    for i in range(len(find_tag)):
        txt = re.sub(r"[^가-힣a-zA-Z0-9]","",str(find_tag[i].get_text())) # 특수문자 제거
        korean_hist[txt] = []

    return korean_hist

def visit_site(visit_url,word):
    word_list = []
    idx = 941
    while idx < 943:
        url = visit_url + word + "/" + "전체" + "?p=" + str(idx) + "&"
        encoded_url = quote(url, safe=':/?&=') # 한글 주소 인코딩
        print(encoded_url)
        res = req.urlopen(encoded_url).read()
        soup = BeautifulSoup(res, 'html.parser') #분석 용이하게 파싱
        find_tag = soup.findAll("div",{"class":"title"}) # "div",{"class":"section_body"}
        if find_tag:
            for i in range(len(find_tag)):
                word_list.append(re.sub(r"[^가-힣a-zA-Z0-9]","",str(find_tag[i].get_text())))
                
            idx += 1
        else:
            break
    print("done")
    print(word_list)
    return word_list


if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    
    parser.add_argument("--url", type=str, default='https://encykorea.aks.ac.kr/')
    parser.add_argument("--visit_url", type=str, default='https://encykorea.aks.ac.kr/Article/List/Type/')

    args = parser.parse_args()

    korean_hist = crawling_list(args.url)
    visit_site(args.visit_url,"인물")
    # for hist in korean_hist:
    #     korean_hist[hist] += visit_site(args.visit_url,hist)
    #     print(hist,"사전의 전체 개수:",len(korean_hist[hist]))

해당 코드의 문제점 

1. 페이지 수를 오버해도 크롤링한다.

2. 페이지 안에 의견주제 (????) 이것도 같이 크롤링 한다.

 

특히 의견주제는 어디서 나온 애인지는 모르겠습니다,,

 

일단 해당 문제점을 고쳐보도록 하겠습니다.

 

크롤링한 페이지의 태그를 보니 해당 태그가 있는 것을 발견했습니다.

<div class="title">
<span class="need">의견 주제</span>
</div>, <div class="title">
<span class="need">의견 주제</span>
</div>, <div class="title">
<span class="need">의견 주제</span>
</div>

함수를 다음과 같이 의견주제가 있으면 포함하지 않는 것으로 합니다..

 

def visit_site(visit_url,word):
    word_list = []
    idx = 1
    while True:
        url = visit_url + word + "/" + "전체" + "?p=" + str(idx) + "&"
        encoded_url = quote(url, safe=':/?&=') # 한글 주소 인코딩
        print(encoded_url)
        print(word_list)
        res = req.urlopen(encoded_url).read()
        soup = BeautifulSoup(res, 'html.parser')#분석 용이하게 파싱
        find_tag = soup.findAll("div",{"class":"title"}) # "div",{"class":"section_body"}

        tmp = []
        for i in range(len(find_tag)):
            txt = re.sub(r"[^가-힣a-zA-Z0-9]","",str(find_tag[i].get_text()))
            if txt != "의견주제": # 특정 태그가 파싱된경우
                tmp.append(txt)
        if tmp:
            word_list.extend(tmp)
            idx += 1
        else:
            break

    print("done")
    
    return word_list

그러면 마지막 페이지를 파싱하면 코드가 종료가 됩니다 ㅎㅎ

 

전체코드

from bs4 import BeautifulSoup
import urllib.request as req 
import argparse # 특정 웹사이트로 접속하기 위해
import re
from urllib.parse import quote
import json

def crawling_list(url):
    res = req.urlopen(url).read()
    soup = BeautifulSoup(res, 'html.parser') #분석 용이하게 파싱
    find_tag = soup.findAll("a",{"class":"depth1-title"}) # "div",{"class":"section_body"}

    korean_hist = dict()
    for i in range(len(find_tag)):
        txt = re.sub(r"[^가-힣a-zA-Z0-9]","",str(find_tag[i].get_text())) # 특수문자 제거
        korean_hist[txt] = []

    return korean_hist

def visit_site(visit_url,word):
    word_list = []
    idx = 1
    while True:
        url = visit_url + word + "/" + "전체" + "?p=" + str(idx) + "&"
        encoded_url = quote(url, safe=':/?&=') # 한글 주소 인코딩
        res = req.urlopen(encoded_url).read()
        soup = BeautifulSoup(res, 'html.parser')#분석 용이하게 파싱
        find_tag = soup.findAll("div",{"class":"title"}) # "div",{"class":"section_body"}

        tmp = []
        for i in range(len(find_tag)):
            txt = re.sub(r"[^가-힣a-zA-Z0-9]","",str(find_tag[i].get_text()))
            if txt != "의견주제": # 특정 태그가 파싱된경우
                tmp.append(txt)
        if tmp:
            word_list.extend(tmp)
            idx += 1
        else:
            break
    
    return word_list

def dict2json(hist_dict,savepath):
    # json 파일로 저장
    with open(savepath + 'korean_hist.json', 'w',encoding="UTF-8") as f : 
        json.dump(hist_dict, f, indent=4)

def readjson(savepath):
    with open(savepath, 'r') as f:
        data = json.load(f)
    print(data)



if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    
    parser.add_argument("--url", type=str, default='https://encykorea.aks.ac.kr/')
    parser.add_argument("--visit_url", type=str, default='https://encykorea.aks.ac.kr/Article/List/Type/')
    parser.add_argument("--savepath", type=str, default='/home/suyeon/code/capstone2/data_crawl/')
    args = parser.parse_args()

    korean_hist = crawling_list(args.url)

    for hist in korean_hist:
        korean_hist[hist].extend(visit_site(args.visit_url,hist))
        print(hist,"사전의 전체 개수:",len(korean_hist[hist]))
    print("done")
    dict2json(korean_hist,args.savepath)

    # readjson(args.savepath)
728x90
반응형