ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [실전] 파이썬으로 웹크롤링을 해보자 - Selenium으로 원하는 정보 크롤링하기
    개발 언어/Python 2024. 4. 1. 15:13
    728x90
    반응형

    부동산 써브에서 관리하고 있는 매물들의 상세내용을 알아와야합니다.

     

    일일이 클릭해서 찾을 수 없으니, 웹크롤링을 해보겠습니다.

     

    먼저 관리하고 있는 매물의 매물번호와 주소가 적힌 엑셀시트를 제공해주어서, 그걸로 매물번호들을 모두 크롤링 해보겠습니다.

     

    selenium을 이용하여 크롤링 해보겠습니다.

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.chrome.options import Options
    import time
    import os
    import requests
    from bs4 import BeautifulSoup
    import re
    import pandas as pd

    이렇게 모듈을 넣어주고요,

     

     

    # 엑셀 파일 경로
    excel_file = "등록종료리스트.xls"
    
    # 엑셀 파일 읽기
    df = pd.read_excel(excel_file)
    
    # A열과 G열의 2번째 행부터 읽어오기
    column_a_values = df.iloc[0:, 0].tolist()  # 'A'열의 숫자 인덱스는 0입니다.
    column_g_values = df.iloc[0:, 6].tolist()  # 'G'열의 숫자 인덱스는 6입니다.
    
    # A열과 G열을 짝지어서 출력 또는 활용할 수 있습니다.
    for a_value, g_value in zip(column_a_values, column_g_values):
        print(f'A열 값: {a_value}, G열 값: {g_value}')

    찾을 놈들을 엑셀에서 긁어옵니다.

     

     

    # Chrome WebDriver 옵션 설정
    chrome_options = Options()
    chrome_options.add_argument("--headless")  # 백그라운드에서 실행하도록 설정
    
    # Chrome WebDriver 생성
    driver = webdriver.Chrome(options=chrome_options)
    
    # 로그인 페이지로 이동
    driver.get("https://m.serve.co.kr/member/login")
    
    
    time.sleep(1)
    # 로그인 폼에 아이디와 비밀번호 입력
    username_field = driver.find_element(By.ID, "input-1")
    print(username_field)
    
    password_field = driver.find_element(By.ID, "input-3")
    
    username_field.send_keys("아이디")
    
    password_field.send_keys("비번")
    
    # 로그인 버튼
    login_button = driver.find_element(By.CLASS_NAME, "t-btn-item")
    login_button.click()
    
    time.sleep(2)

    크롬 웹드라이버를 열고 로그인페이지로 가서 로그인을 해줍니다.

    그래야 매물을 볼 수 있거든요.

     

    html에서 로그인과 패스워드, 그리고 로그인 버튼의 id를 알아옵니다.

    그 위치에 값을 넣고 클릭할 수 있어요.

     

     

    for atclNo, atclNo_address in zip(column_a_values, column_g_values):
        print("시작 : ", atclNo, atclNo_address )
        work_folder = atclNo_address
        atclNo_str = str(atclNo)
        image_folder = os.path.join(work_folder, atclNo_str)
    
        if not os.path.exists(work_folder):
            os.makedirs(work_folder)

    자, 이제 for문을 돌려서 모든 매물번호를 크롤링해보겠습니다.

     

    # # 대상 URL 설정
        url = "https://ma.serve.co.kr/good/articleRegistManage?atclNo="+atclNo_str+"&type=articleReInsert"
    
        # # 해당 URL로 이동
        driver.get(url)
    
        time.sleep(5)

     

     

    url은 다행히 매물번호가 들어가는 위치가 따로 있어서 어렵지 않겠네요

     

     

     

    이제 원하는 곳을 크롤링 할건데요,

    양식이 동일하다면 XPath 를 이용하면 편합니다.

     

     

    저 XPath에는 동적으로 값이 할당되어있는것으로 나와요.

    html을 다운받아서 찾아보면 안나옵니다.

     

    Java Script를 활용해서 가져와볼게요.

    # JavaScript 코드 실행
        script = """
        var xpath = '//*[@id="app"]/div/div/div[3]/div/div[1]/div[14]/table/tbody/tr[3]/td/div/div[1]/div/div[3]/label'; 
        var element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
        if (element) {
            var element_for = element.getAttribute("for");
            var element_id = document.getElementById(element_for);
            var value = element_id.value;
            if (value) {
                return value;
            }
            else {
                var xpath = '//*[@id="app"]/div/div/div[3]/div/div[1]/div[13]/table/tbody/tr[3]/td/div/div[1]/div/div[3]/label'; 
                var element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                if (element) {
                    var element_for = element.getAttribute("for");
                    var element_id = document.getElementById(element_for);
                    var value = element_id.value;
                    if (value) {
                        return value;
                    }
                    else {
                        return "요소를 찾을 수 없습니다.";
                    }
                }
                else {
                    return "요소를 찾을 수 없습니다.";
                }
            }
        }
        else{
            var xpath = '//*[@id="app"]/div/div/div[3]/div/div[1]/div[13]/table/tbody/tr[3]/td/div/div[1]/div/div[3]/label'; 
            var element = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
            if (element) {
                var element_for = element.getAttribute("for");
                var element_id = document.getElementById(element_for);
                var value = element_id.value;
                return value;
            }
            else {
                return "요소를 찾을 수 없습니다.";
            }
        }
        
        # 3번 반복하는 반복문
        for idx in range(3):
            # JavaScript 코드 실행
            result1 = driver.execute_script(script)
            
            # 결과 확인 후 처리
            if result1 == "요소를 찾을 수 없습니다.":
                # 대상 URL 설정
                url = "https://ma.serve.co.kr/good/articleRegistManage?atclNo=" + atclNo_str + "&type=articleReInsert"
                # 해당 URL로 이동
                driver.get(url)
                time.sleep(5)
                print("요소를 찾을 수 없습니다.", idx)
            else:
                break

     

    '//*[@id="app"]/div/div/div[3]/div/div[1]/div[13]/table/tbody/tr[3]/td/div/div[1]/div/div[3]/label'; 

     

    Xpath의 위치가, div[13]도 있고 div[14]도 있어서

    둘중에 비어있지 않은걸 가져오기로 했어요.

     

    이제 가져온 결과를 저장해야겠죠?

     

    # 결과를 텍스트 파일에 저장
        file_name_txt = work_folder+"\\"+atclNo_str+".txt"
        with open(file_name_txt, "w") as file:
            file.write(str(result1))

    파일을 열어서 안에 내용을 저장해줍니다.

     

    그럼 폴더 안에 크롤링된 결과가 저장된걸 알수 있어요

     

    html은 저장되어있는 사진의 url을 추출해서 저장하기 위해 넣었습니다.

     

    # 정규 표현식 패턴
        pattern = r"https://newimg\.serve\.co\.kr/article_photo/\S+\.jpg"
    
        # 정규 표현식을 사용하여 URL 추출
        urls = re.findall(pattern, html_content)
    
        # 각 URL을 순회하면서 이미지를 다운로드
        for idx, url in enumerate(urls, start=1):
            if not os.path.exists(image_folder):
                os.makedirs(image_folder)
    
            response = requests.get(url)
            if response.status_code == 200:
                # URL에서 파일명 추출
                filename = os.path.join(image_folder, f"image_{idx}.jpg")
                # 이미지 저장
                with open(filename, "wb") as image_file:
                    image_file.write(response.content)
    
            else:
                print(f"이미지 다운로드 실패: {url}")
        print("종료")

     

    무려 300개의 가까운 자료를 정확하게 찾아내서 잘 담아두었습니다~

     

    728x90
    반응형

    댓글

Designed by Tistory.