본문 바로가기
코딩 연습/코딩배우기

파이썬 웹 크롤링(Web Crawling) 알아보기 #9

by good4me 2020. 10. 26.

goodthings4me.tistory.com

 

■ 파이썬 크롤링 실습 - 국회사이트 국회의원 목록

국회(assembly.go.kr) 사이트의 국회의원 현황 페이지의 목록이 '페이지 소스 보기"에서는 안보임 
https://assembly.go.kr/assm/memact/congressman/memCond/memCond.do

개발자도구(F12) Network탭에서 목록이 확인됨
https://assembly.go.kr/assm/memact/congressman/memCond/memCondListAjax.do

하단 페이지 클릭 시 Request Method: POST 방식이기 때문에 파라미터가 필요한데, 
페이지 클릭 시 Network탭 하단의 Form Data 부분을 보면
currentPage가 1, 7, 13, 19,... 순으로 변경되고 rowPerPage: 6 인 것을 확인할 수 있음
https://assembly.go.kr/assm/memact/congressman/memCond/memCondListAjax.do?currentPage=1&rowPerPage=6

currentPage는 국회의원 순서(가나다라 순)이고, rowPerPage는 한 페이지에 출력할 의원수임
rowPerPage를 300명 전체 대상으로 출력해서 목록 전체를 추출할 수 있음

good4me.co.kr

import requests
from bs4 import BeautifulSoup
import re

url = 'https://assembly.go.kr/assm/memact/congressman/memCond/memCondListAjax.do?\
currentPage=1&rowPerPage=300'

html = requests.get(url)
#print(html)
soup = BeautifulSoup(html.text, 'html.parser')

cnt = 0
assem_list = []
for tag in soup.select('.memberna_list dl'):
    cnt += 1
    
    intro = []
    name = tag.find('a').text
    name_han = tag.select_one('.chi').text.strip() # 한문이름
    chojae = tag.select_one('.mt').text  # 초/재선
    local = tag.select_one('.ht').text  # 지역구 주소
    intro.append('\n\n' + str(cnt) + '\n' + name + name_han)
    intro.append(chojae)
    intro.append(local)
    assem_list.append(intro)
    
    # javascript 코드에서 의원 구분 코드 추출을 위해 정규표현식 사용
    matched = re.search(r'\d+', tag.find('a')['href'])
    if matched:
        member_id = matched.group(0)
    else:
        member_id = None
    
    # 이름에 링크된 주소와 member_id
    # https://assembly.go.kr/assm/memPop/memPopup.do?dept_cd=9770936
    member_url = 'https://assembly.go.kr/assm/memPop/memPopup.do'
    params = {
        'dept_cd': member_id,
    }
    
    html = requests.get(member_url, params = params)
    #print(html)
    soup = BeautifulSoup(html.text, 'html.parser')
        
    for tag in soup.select('.info_mna > ul'):
        for tag_left in tag.select('.left'):
            profile = tag_left.select('li')
            intro.append(profile[3].text)  # 생년월일
        #print(intro)
        
        # 약력 부분 추출
        # " " <br> 부분에 대해 get_text(strip=True, separator=" ") 사용
        career = []
        for tag_left in tag.select('.per_history dd'):
            ca = tag_left.get_text(strip=True, separator="\n")
            career.append(ca)
        assem_list.append(career)

        for tag_right in tag.select('.right > .pro_detail'):
            # 세부 프로필 중 항목 부분 추출
            dt_list = []
            for dt_tag in tag_right.select('dt:nth-child(2n + 1)'):
                dt_list.append(dt_tag.text.strip())
            
            # 세부 프로필 중 항목별 내용 부분 추출
            dd_list = []
            for dd_tag in tag_right.select('dd:nth-child(2n)'):
                # 정규표현식으로 공백, 탭, 개행 문자 제거
                dd = re.sub(r'[\s+\t\r\n]', '', dd_tag.text.strip())
                dd_list.append(dd)
            
            # 항목과 내용을 묶어서 리스트에 추가
            dtd = []
            for i in range(len(dt_list)):
                if i == 0:
                    dtd.append('\n' + dt_list[i] + ': ' + dd_list[i])
                else:
                    dtd.append(dt_list[i] + ': ' + dd_list[i])
                
            assem_list.append(dtd)
            
            #print(assem_list)
            
    if cnt == 5:
        break


for assem in assem_list:
    for a in assem:
        print(a)

 

[참고] askcompany.kr - 크롤링 차근차근 시작하기

 

댓글