Categories: '교육'

[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python

[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python l 가끔 업체 조사를 할 때면 각 업체의 대표자, 주소, 설립일, 매출 등을 살펴봅니다. 네이버에서 보면 나이스 신용평가에서 제공하는 서비스가 링크가 걸려있는데 이 링크를 클릭하면 그 회사의 정보를 얻을 수 있습니다. 하지만 여러 업체를 조사하려면 꽤 시간이 많이 걸리죠. 그래서 이 노가다 작업을 쉽게 하기 위해서 코드를 하나 만들어 보려고합니다.

[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python

먼저 네이버에서 해당 정보를 얻기 위해서 구조를 살펴보면 업체를 검색한 뒤, 주소가 바뀌는 패던을 보면 kiscode 값이 바뀌는 것을 볼 수 있습니다. 업체의 고유 번호 같은 것인데, 이 코드를 받은 후 나이스 평가 사이트에서 이 값을 다시 넣어서 업체를 조회하는 패턴으로 코드를 작성해주려고 합니다.

[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python

[나이스 평가 사이트에서는 무단 크롤링을 엄격히 금지하고 있으니 공부 목적으로만 사용하시기 바랍니다. 고유 지적 재산에 해당 할 수 있으니 이 코드를 유료로도 판매하지 마시고, 또 공부 외의 목적으로는 절대 남용하지 마십시오]

아래 보면 (주)삼성전자 의 KISCODE 를 확인할 수 있습니다.

[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python
[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python

이렇게 조회한 정보에서 대표자 ~ 상장일자 정보까지 추출해 보겠습니다.

import streamlit as st
import pandas as pd
import requests
from bs4 import BeautifulSoup
import ssl
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
import re
import time

# SSL/TLS 설정을 위한 어댑터 클래스
class TLSAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        context = ssl.create_default_context()
        context.set_ciphers('DEFAULT:@SECLEVEL=1')
        kwargs['ssl_context'] = context
        return super().init_poolmanager(*args, **kwargs)

# 세션 생성 및 어댑터 설정
session = requests.Session()
session.mount('https://', TLSAdapter())

# 네이버 검색 결과에서 kiscode 추출 함수
def find_kiscode_from_naver_search(query):
    search_url = 'https://search.naver.com/search.naver'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
    }
    params = {
        'where': 'nexearch',
        'sm': 'top_hty',
        'fbm': '0',
        'ie': 'utf8',
        'query': query
    }

    try:
        response = session.get(search_url, headers=headers, params=params)
        response.raise_for_status()
        soup = BeautifulSoup(response.content, 'html.parser')
        
        more_info_link = soup.find('a', class_='info_more', href=True)
        if more_info_link and 'kiscode=' in more_info_link['href']:
            kiscode = re.search(r'kiscode=([A-Za-z0-9]+)', more_info_link['href'])
            if kiscode:
                return kiscode.group(1), more_info_link['href']
        return None, None
    except requests.RequestException as e:
        st.error(f"Request failed: {e}")
        return None, None

# 나이스 사이트에서 업체 정보를 가져오는 함수
def get_company_info(kiscode):
    url = f'https://www.nicebizinfo.com/ep/EP0100M002GE.nice?kiscode={kiscode}'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
    }
    
    try:
        response = session.get(url, headers=headers)
        response.raise_for_status()
        soup = BeautifulSoup(response.content, 'html.parser')
        
        company_info = {
            '대표자': soup.find('p', string='대표자').find_next_sibling('strong').get_text(strip=True) if soup.find('p', string='대표자') else '',
            '본사주소': soup.find('p', string='본사주소').find_next_sibling('strong').get_text(strip=True) if soup.find('p', string='본사주소') else '',
            '그룹명': soup.find('p', string='그룹명').find_next_sibling('strong').get_text(strip=True) if soup.find('p', string='그룹명') else '',
            '사업자번호': soup.find('p', string='사업자번호').find_next_sibling('strong').get_text(strip=True) if soup.find('p', string='사업자번호') else '',
            '기업형태': soup.find('p', string='기업형태').find_next_sibling('strong').get_text(strip=True) if soup.find('p', string='기업형태') else '',
            '산업': soup.find('p', string='산업').find_next_sibling('strong').get_text(strip=True) if soup.find('p', string='산업') else '',
            '설립일자': soup.find('p', string='설립일자').find_next_sibling('strong').get_text(strip=True) if soup.find('p', string='설립일자') else '',
            '상장일자': soup.find('p', string='상장일자').find_next_sibling('strong').get_text(strip=True) if soup.find('p', string='상장일자') else ''
        }
        
        revenue_row = soup.find('tr', class_='bdBck fwb')
        if revenue_row:
            revenues = revenue_row.find_all('td', class_='tar')
            revenue_data = []
            for td in revenues:
                text = td.get_text(strip=True).replace(',', '').replace(' ', '')
                if text.isdigit():
                    revenue_data.append(f"{int(text):,} 원")
                else:
                    revenue_data.append(text)
        else:
            revenue_data = ['', '', '']
        
        return company_info, revenue_data
    except requests.RequestException as e:
        st.error(f"Request failed: {e}")
        return {}, ['', '', '']

# 스트림릿 웹 앱 구성
def main():
    st.title("업체 정보 조회기")
    
    # 옵션 선택: 직접 입력 vs 엑셀 업로드
    option = st.radio("업체명을 직접 입력하시겠습니까, 아니면 엑셀 파일을 업로드하시겠습니까?", ("직접 입력", "엑셀 업로드"))

    if option == "직접 입력":
        company_name = st.text_input("업체명을 입력하세요:")
        if st.button("조회"):
            kiscode, nice_info_url = find_kiscode_from_naver_search(company_name)
            if kiscode:
                company_info, revenue_data = get_company_info(kiscode)
                result = {
                    '업체명': company_name,
                    'kiscode': kiscode,
                    '대표자': company_info.get('대표자', ''),
                    '본사주소': company_info.get('본사주소', ''),
                    '그룹명': company_info.get('그룹명', ''),
                    '사업자번호': company_info.get('사업자번호', ''),
                    '기업형태': company_info.get('기업형태', ''),
                    '산업': company_info.get('산업', ''),
                    '설립일자': company_info.get('설립일자', ''),
                    '상장일자': company_info.get('상장일자', ''),
                    '2023년 매출': revenue_data[0],
                    '2022년 매출': revenue_data[1],
                    '2021년 매출': revenue_data[2]
                }
                st.write(result)
            else:
                st.write(f"업체 '{company_name}'를 찾을 수 없습니다.")
    
    elif option == "엑셀 업로드":
        uploaded_file = st.file_uploader("업로드할 엑셀 파일을 선택하세요.", type=["xlsx"])
        
        if uploaded_file is not None:
            df = pd.read_excel(uploaded_file)
            if '업체명' not in df.columns:
                st.error("엑셀 파일에 '업체명' 열이 존재하지 않습니다.")
                return
            
            results = []
            total_companies = len(df)
            completed_count = 0
            failed_count = 0
            progress_placeholder = st.empty()
            
            for idx, company_name in enumerate(df['업체명']):
                kiscode, nice_info_url = find_kiscode_from_naver_search(company_name)
                company_info, revenue_data = ({'대표자': '', '본사주소': '', '그룹명': '', '사업자번호': '', '기업형태': '', '산업': '', '설립일자': '', '상장일자': ''}, ['', '', '']) if not kiscode else get_company_info(kiscode)
                
                result = {
                    '업체명': company_name,
                    'kiscode': kiscode if kiscode else '',
                    '대표자': company_info.get('대표자', ''),
                    '본사주소': company_info.get('본사주소', ''),
                    '그룹명': company_info.get('그룹명', ''),
                    '사업자번호': company_info.get('사업자번호', ''),
                    '기업형태': company_info.get('기업형태', ''),
                    '산업': company_info.get('산업', ''),
                    '설립일자': company_info.get('설립일자', ''),
                    '상장일자': company_info.get('상장일자', ''),
                    '2023년 매출': revenue_data[0],
                    '2022년 매출': revenue_data[1],
                    '2021년 매출': revenue_data[2]
                }
                results.append(result)
                
                if kiscode:
                    completed_count += 1
                else:
                    failed_count += 1
                
                remaining_count = total_companies - (idx + 1)
                progress = (idx + 1) / total_companies * 100
                progress_placeholder.write(f"진척율: {progress:.2f}% | 완료: {completed_count}개 | 실패: {failed_count}개 | 남은 작업 수: {remaining_count}개")
                
                # 각 요청 사이에 3초 딜레이 추가
                time.sleep(1.5)
            
            # 결과 출력
            results_df = pd.DataFrame(results)
            if not results_df.empty:
                st.write(results_df)
            
            if failed_count > 0:
                st.write("다음 업체들은 정보를 찾을 수 없었습니다:")
                st.write([res['업체명'] for res in results if not res['kiscode']])
    
if __name__ == "__main__":
    main()

이렇게 추출한 코드는 streamlit에서 돌리면 아름다운 코드로 바뀌는 것을 볼 수 있습니다.

[업체 정보] 대표자, 주소, 매출을 한눈에 살펴보기 with python

urjent

Share
Published by
urjent

Recent Posts

월드컵 파라과이 퇴장: 미겔 알미론, 입 가리고 조롱해 첫 퇴장 선수로 기록

2026년 6월 20일 미국 캘리포니아주 샌프란시스코 베이 에어리어 스타디움에서 열린 북중미 월드컵 D조 조별리그 2차전…

5시간 ago

내신 리셋 늘고 있다…고1 자퇴 후 재입학 사례 급증, 5등급제 전환 후 변화

내신 5등급제가 본격적으로 적용된 이후 고등학교 1학년 성적이 대학 입시에 미치는 영향이 커지면서, ‘내신 리셋’을…

5시간 ago

남편들 영화 내용 배우 진선규 공명 케미, 6월 19일 넷플릭스 공개

넷플릭스 오리지널 영화 '남편들'은 2026년 6월 19일 전 세계에 단독 공개됩니다. 이 영화는 박규태 감독의…

11시간 ago

여고생 살해범 장윤기 첫 재판 6월 22일 열린다, 강간 등 살인 혐의 적용 쟁점

여고생 흉기 살해 사건의 피고인 장윤기(23)에 대한 첫 공판이 2026년 6월 22일 오전 10시 광주지방법원…

12시간 ago

류혜영 응팔 후 불안해져 암막커튼까지 걷지 못하는 이유와 극복 과정

배우 류혜영은 '응답하라 1988' 종영 후 쏟아진 관심으로 심각한 불안감을 경험했다고 공개적으로 밝혔습니다. 특히 2026년…

12시간 ago

중앙일보 부도처리, 220억 기업어음 조기상환 실패로 1차 부도

[두괄식 도입. 첫 문장에 가장 중요한 결론이나 사실을 직접 명시. 참고자료의 핵심 내용을 바탕으로 3~4문장…

1일 ago