인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

최지훈님의 프로필 이미지

작성한 질문수

[신규 개정판] 이것이 진짜 크롤링이다 - 실전편 (인공지능 수익화)

find_elements 텍스트

작성

·

1.5K

1

안녕하십니까 강사님

전에 find_elements의 리스트 결과에서 텍스트를 뽑아내는 방법을 여쭤봤습니다.

그런데 구글검색을 한 결과나 강사님께서 주신 답이나 둘 다 똑같이 반복문을 이용하면 된다는 말 뿐이고
실질적으로 어떻게 해야할지 감이 잘 잡히지 않는데,
아래 예시에서 어떤 식으로 반복문을 활용해야 할지 궁금해서 질문드립니다.

 

뽑아내고 싶은 텍스트:

if len(li.find_elements(By.CSS_SELECTOR, "span._2FqTn._4DbfT")) > 0:

(1) 네이버 맛집 검색 결과에서 len을 사용해 영업중인지 여부를 파악하는것 + (2) 영업중이라면 "영업중"이라는 결과가 text로 나오게 하는 것

 

전체 명령어

# 데이터 저장 후 마무리
import imp
from lib2to3.pgen2 import driver
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
import pyautogui
import openpyxl

keyword = pyautogui.prompt("검색어를 입력하세요")

wb = openpyxl.Workbook()
ws = wb.create_sheet(keyword)
ws.append(["순위", "이름", "별점", "방문자리뷰", "블로그리뷰"])

# 크롬 드라이버 자동 업데이트
from webdriver_manager.chrome import ChromeDriverManager

# 브라우저 자동으로 꺼짐 방지
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)

# 불필요한 에러 메시지 삭제
chrome_options.add_experimental_option("excludeSwitches", ["enable-logging"])

# 셀레니움으로 웹브라우저 자동으로 띄우기
# ChromeDriverManager를 통해서 ChromeDriver를 설치하고, Service라는 객체를 만든 뒤, service라는 변수에 저장한다
service = Service(executable_path=ChromeDriverManager().install())
browser = webdriver.Chrome(service=service, options=chrome_options)

# 특정 웹페이지 주소로 이동
browser.implicitly_wait(5) # 웹페이지가 로딩 될때까지 5초는 기다려준다
browser.maximize_window() # 화면 최대화
browser.get('https://map.naver.com/v5/?c=14141023.2182021,4522932.8702864,15,0,0,0,dh')

# 검색 배너 클릭
search = browser.find_element(By.CSS_SELECTOR, "input.input_search")
search.click()
time.sleep(1)

# 검색어 입력
search.send_keys(keyword)
search.send_keys(Keys.ENTER) # 검색어를 입력하고, 엔터를 치라는 명령어
time.sleep(2)

# iframe 안으로 들어가기
browser.switch_to.frame("searchIframe") # searchIframe는 iframe의 id다.

# 들어가는 것과 반대로, iframe 밖으로 나와서 원래 사이트로 돌아가는것
# browser.switch_to_default_content()

# iframe 안쪽 클릭하기
browser.find_element(By.CSS_SELECTOR, "#_pcmap_list_scroll_container").click()

# 로딩된 데이터 개수 확인
lis = browser.find_elements(By.CSS_SELECTOR, "li._1EKsQ")
before_len = len(lis) # lis를 통해 각 가게를 나타내는 li를 가져오고, len을 통해 몇 개가 있는지를 확인한다.

while True:
    # 맨 아래로 스크롤을 내리자.
    browser.find_element(By.CSS_SELECTOR, "body").send_keys(Keys.END) # 아무 태그나 선택하기 위해서 body를 선택한다.
    # 스크롤 사이에 페이지 로딩 시간을 기다려주자
    time.sleep(1.5)
    # 스크롤 후 로딩된 데이터 개수 확인
    lis = browser.find_elements(By.CSS_SELECTOR, "li._1EKsQ")
    after_len = len(lis)
    # print("스크롤 전", before_len, "스크롤 후", after_len)를 추가해서, 실제로 스크롤이 잘 되는지 결과를 확인할 수 있다(word 참조)
   
    # 로딩된 데이터 개수가 같아지면(= 한 페이지에서 더이상 스크롤을 내려도 새로운 정보가 없다면) 반복 멈춰라
    if before_len == after_len:
        break
    before_len = after_len # 만약 before_len == after_len가 True가 아니라면, before_len을 after_len으로 만들어주라

# for문 시작하기 전에, 데이터 기다리는 시간을 0으로 만들어주자(데이터가 없는건 그냥 빠르게 넘어간다)
browser.implicitly_wait(0)

rank = 1
for li in lis: # lis는 가게 정보를 담고 있으니까 여기에 for문을 써서 가게정보를 가져오자
    # 광고상품 아닌 것만 -> len을 넣어서 결과가 0이라면 광고 CSS에 아무 결과가 없다는 뜻이다.
    # 그 뒤, 아래 기존 명령어를 전부 drag하고 tab을 눌러주자.
    if len(li.find_elements(By.CSS_SELECTOR, "svg._2ulu3")) == 0:
        # 별점이 있는 가게만 가져오자
        # 별점부분 정보를 가져왔을 때, 해당 리스트의 길이가 0보다 크다면, 즉, 무언가 별점에 관한 정보가 있다면 명령문을 진행한다.    
        if len(li.find_elements(By.CSS_SELECTOR, "span._2FqTn._1mRAM > em")) > 0: # word 참조
            # 가게명
            name = li.find_element(By.CSS_SELECTOR, "span.place_bluelink.OXiLu").text
            # 별점
            star = li.find_element(By.CSS_SELECTOR, "span._2FqTn._1mRAM > em").text

            # 영업 시간이 있다면?
            if len(li.find_elements(By.CSS_SELECTOR, "span._2FqTn._4DbfT")) > 0: # 영업중이든 종료든 무언가 정보가 있다면 다음을 실행하라는 뜻
                # 방문자 리뷰수
                try:
                    visit_review = li.find_element(By.CSS_SELECTOR, "span._2FqTn:nth-child(3)").text
                except:
                    visit_review = "0" # try의 결과가 text니까, try의 명령어가 True가 아닌 결과값도 ""를 통해 text 형태로 만들어주자.
                # 블로그 리뷰수
                try:
                    blog_review = li.find_element(By.CSS_SELECTOR, "span._2FqTn:nth-child(4)").text
                except:
                    blog_review = "0"
            # 영업 시간이 없다면: 제일 앞에 span 태그가 하나 사라지니까, nth-child도 하나씩 숫자를 줄이자
            else:
                # 방문자 리뷰수
                try:
                    visit_review = li.find_element(By.CSS_SELECTOR, "span._2FqTn:nth-child(2)").text
                except:
                    visit_review = "0"
                # 블로그 리뷰수
                try:
                    blog_review = li.find_element(By.CSS_SELECTOR, "span._2FqTn:nth-child(3)").text
                except:
                    blog_review = "0"
            # print 전 데이터 전처리
            visit_review = visit_review.replace("방문자리뷰 ", "").replace(",", "")
            blog_review = blog_review.replace("블로그리뷰 ", "").replace(",", "")
            print(rank, name, star, visit_review, blog_review)
            ws.append([rank, name, float(star), int(visit_review), int(blog_review)])
            rank = rank + 1 # rank를 저장한 뒤, for문 마지막에 1개 더 높여주자.
wb.save(f"{keyword}.xlsx")

 

 

 

 

답변 1

0

스타트코딩님의 프로필 이미지
스타트코딩
지식공유자

영업 중 텍스트를 추출해서 엑셀에 저장하도록 수정해 봤습니다.

 

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time
import pyautogui
import openpyxl


keyword = pyautogui.prompt("검색어를 입력하세요")

wb = openpyxl.Workbook()
ws = wb.create_sheet(keyword)
ws.append(["순위", "이름", "별점", "방문자리뷰", "블로그리뷰", "영업중"])

browser = webdriver.Chrome("c:/chromedriver.exe")
browser.get("https://map.naver.com/v5/")
browser.implicitly_wait(10)
browser.maximize_window()

# 검색창 입력
search = browser.find_element(By.CSS_SELECTOR ,"input.input_search")
search.click()
time.sleep(1)
search.send_keys(keyword)
time.sleep(1)
search.send_keys(Keys.ENTER)
time.sleep(2)

# iframe 안으로 들어가기
browser.switch_to.frame("searchIframe")

# browser.switch_to_default_content() iframe 밖으로 나오기

# iframe 안쪽을 한번 클릭하기
browser.find_element(By.CSS_SELECTOR ,"#_pcmap_list_scroll_container").click()

# 로딩된 데이터 개수 확인
lis = browser.find_elements(By.CSS_SELECTOR ,"li._1EKsQ")
before_len = len(lis)

while True:
    # 맨 아래로 스크롤 내린다.
    browser.find_element(By.CSS_SELECTOR ,"body").send_keys(Keys.END)

    # 스크롤 사이 페이지 로딩 시간
    time.sleep(1.5)

    # 스크롤 후 로딩된 데이터 개수 확인
    lis = browser.find_elements(By.CSS_SELECTOR ,"li._1EKsQ")
    after_len = len(lis)

    # 로딩된 데이터 개수가 같다면 반복 멈춤
    if before_len == after_len:
        break
    before_len = after_len

# 데이터 기다리는 시간을 0으로 만들어 줘요. (데이터가 없더라도 빠르게 넘어감)
browser.implicitly_wait(0)

rank = 1
for li in lis:
    # 광고 상품 아닌 것만
    if len(li.find_elements(By.CSS_SELECTOR ,"svg._2ulu3")) == 0:
        # 별점이 있는 것만
        if len(li.find_elements(By.CSS_SELECTOR ,"span._2FqTn._1mRAM > em")) > 0:
            # 가게명
            name = li.find_element(By.CSS_SELECTOR ,"span.OXiLu").text
            # 별점
            star = li.find_element(By.CSS_SELECTOR ,"span._2FqTn._1mRAM > em").text

            # 영업 시간이 있다면
            if len(li.find_elements(By.CSS_SELECTOR ,"span._2FqTn._4DbfT")) > 0:
                # 영업중
                open = li.find_element(By.CSS_SELECTOR ,"span._2FqTn._4DbfT").text
           

                # 방문자 리뷰수
                try:
                    visit_review = li.find_element(By.CSS_SELECTOR ,"span._2FqTn:nth-child(3)").text
                except:
                    visit_review = "0"
                # 블로그 리뷰수
                try:
                    blog_review = li.find_element(By.CSS_SELECTOR ,"span._2FqTn:nth-child(4)").text
                except:
                    blog_review = "0"
            # 영업 시간이 없다면
            else:
                # 영업중
                open = li.find_element(By.CSS_SELECTOR ,"span._2FqTn._4DbfT").text

                # 방문자 리뷰수
                try:
                    visit_review = li.find_element(By.CSS_SELECTOR ,"span._2FqTn:nth-child(2)").text
                except:
                    visit_review = "0"
                # 블로그 리뷰수
                try:
                    blog_review = li.find_element(By.CSS_SELECTOR ,"span._2FqTn:nth-child(3)").text
                except:
                    blog_review = "0"

            # 데이터 전처리
            visit_review = visit_review.replace("방문자리뷰 ", "").replace(",", "")
            blog_review = blog_review.replace("블로그리뷰 ", "").replace(",", "")

            print(rank, name, star, visit_review, blog_review)
            ws.append([rank, name, float(star), int(visit_review), int(blog_review), open])
            rank = rank + 1

wb.save(f"09_네이버_지도_크롤링/{keyword}.xlsx")