월 15,400원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결이것이 진짜 크롤링이다 - 실전편
webdriver_manager 모듈이 인식이 안되는것 같아요
from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options # 크롬 드라이버 자동 업데이트 from webdriver_manager.chrome import ChromeDriverManager service = Service(executable_path=ChromeDriverManager().install())위와 같이 코딩하고 실행하면 Traceback (most recent call last): File "c:\Users\omonge\Desktop\파이썬공부\desktop\requests_1.py", line 7, in <module> from webdriver_manager.chrome import ChromeDriverManagerModuleNotFoundError: No module named 'webdriver_manager'위와 같이 모듈이 없다고 하면서 오류가 발생하는데요. pip install webdriver_manager 라이브러리 설치도 했고 pip list 에도 webdriver-manager 3.8.3설치가 된 것으로 나오는데요. 라이브러리 설치 인식이 안되는걸까요?검색해보고 컴퓨터도 껐다 켜보고.. 했는데요. 계속 인식이 안되는것 같아요 ㅠ윈도우10 입니다.
- 미해결이것이 진짜 크롤링이다 - 실전편
섹션 2 쿠팡크롤링 첫번째 강의에서
Accept-Language가 필요한건 혹시 인터넷에서 어떤 참고자료를 찾으셨나요? 어떤건지 정확히 알고 싶은데 구글링을 해도 어렵네요 ㅠㅠㅠ
- 미해결이것이 진짜 크롤링이다 - 실전편
멈춤현상
안녕하세요! 여전히 멈춤현상이 있는데 해결방안은 언제쯤 확인이 가능할까요? 확인부탁드립니다!
- 미해결이것이 진짜 크롤링이다 - 실전편
find_elements 텍스트
안녕하십니까 강사님 전에 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")
- 미해결이것이 진짜 크롤링이다 - 실전편
f string
안녕하십니까 강사님f string 관련 질문드리고 싶은게 있습니다. f string을 통해 바뀌는 문자열을 표현해줄 수 있는 것으로 이해했는데,정확히 어떤 상황에서 사용하는 것이 적절할지는 확실히 이해하지 못 했습니다. 예를 들어, keyword = pyautogui.prompt("검색어를 입력하세요") ws = wb.create_sheet(keyword) search.send_keys(keyword) wb.save(f"{keyword}.xlsx") requests.get('https://search.naver.com/search.naver?where=news&sm=tab_jum&query=' + keyword) f'https://search.naver.com/search.naver?where=news&sm=tab_jum&query={keyword}' 위와 같이 다양한 상황에서 keyword라는 변수를 사용하는데, 어디는 f string, 어디는 그냥 변수명만 사용합니다. 어떤 기준에서 쓰임을 구분할 수 있는지 말씀해주시면 정말 감사하겠습니다. 질문이 많아 죄송합니다. 너무나 유익한 강의 감사드립니다.
- 미해결이것이 진짜 크롤링이다 - 실전편
find_elements 텍스트
안녕하십니까 강사님.find_elements에서 text를 뽑아내는 방법을 여쭈고 싶습니다. 네이버지도 데이터를 수집하면서 "영업중" 여부를 파악하기 위해 아래와 같은 명령문을 작성하셨습니다. if len(li.find_elements(By.CSS_SELECTOR, "span._2FqTn._4DbfT")) > 0: 그런데, 영업중인지 아닌지 text도 뽑아보려고 하니, .text 명령어는 find_element에서만 사용할 수 있고, find_elements에서는 .text 대신 for 문을 사용해서 텍스트 정보를 따로 뽑아내야 한다는 내용을 알게 되었습니다. 그러나, 예시를 보고 수행해봐도 원하는 결과를 얻을 수 없어 강사님께 여쭈고 싶습니다. li.find_elements(By.CSS_SELECTOR, "span._2FqTn._4DbfT").text 위와 같이 find_elements에서 .text를 실행하는 방법이 있다면, 말씀해주시면 감사하겠습니다.
- 미해결이것이 진짜 크롤링이다 - 실전편
이미지 크롤링시 질문있어요!!
이것이 진짜 크롤링이다 - 실전편 네이버 이미지 주소추출 수업을 듣고있다가 질문드려요! 이미지의 URL을 크롤링 하던 중 약 550개 이미지 URL 크롤링 중 350개 정도는 아래와 같이 URL이 크롤링 되더라구요 .. 그러면서 이미지 다운도 안되구요.. 뭐가 문제일까요 .ㅠ 도와주세요! data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7 == 소스 코드== from webbrowser import BackgroundBrowser from selenium import webdriver import time from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.by import By options = webdriver.ChromeOptions() options.add_experimental_option("excludeSwitches", ["enable-logging"]) url = "https://search.naver.com/search.naver?where=image&sm=tab_jum&query=%EB%A7%A5%EB%B6%81" browser = webdriver.Chrome("C:/chromedriver.exe") browser.implicitly_wait(10) browser.maximize_window() browser.get(url) # 무한 스크롤 처리 # 스크롤 전 높이 before_h = browser.execute_script("return window.scrollY") # 무한 스크롤 while True: #맨 아래로 스크롤을 내린다. # browser.find_element(By.CSS_SELECTOR,"body").send_keys(Keys.END) browser.find_element_by_css_selector("body").send_keys(Keys.END) # 스크롤 사이 페이지 로딩 시간 time.sleep(3) # 스크롤 후 높이 after_h = browser.execute_script("return window.scrollY") if after_h == before_h: break before_h = after_h # 이미지 태그 추출 imgs = browser.find_elements_by_css_selector("a.link_thumb._imageBox._infoBox>._image._listImage") for i, img in enumerate (imgs,1) : img_src = img.get_attribute("src") print(i, img_src)
- 미해결이것이 진짜 크롤링이다 - 실전편
큰 사진 가져오기 오류
안녕하십니까큰 사진 가져올 때 오류가 발생하여 질문드립니다. 강사님과 같이 2번째 사진부터 작은 사진이 받아지기 시작했고, html을 보니, 1번째 사진은 2가지 img.n3VNCb 중 1번 url 2번째 이후부터는 3가지 img.n3VNCb 중 2번 url에 사진이 정확히 연결되는 것을 확인했습니다. 따라서 # 큰 이미지 주소 추출 if i == 1: target = browser.find_elements(By.CSS_SELECTOR, "img.n3VNCb")[0] else: target = browser.find_elements(By.CSS_SELECTOR, "img.n3VNCb")[1] img_src = target.get_attribute("src") 위와 같은 코딩을 추가했습니다. 1. 2번째 사진부터 작은 사진이 받아지는 문제는 해결됨 2.. 강의 영상에 나오는 오류해결 방법을 모두 해봤지만, 2번째 사진 이후, 3번째사진부터는 다운로드가 되지 않음 3. 오류는 아래와 같이 발생 Traceback (most recent call last): File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 1348, in do_open h.request(req.get_method(), req.selector, req.data, headers, File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\http\client.py", line 1282, in request self._send_request(method, url, body, headers, encode_chunked) File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\http\client.py", line 1328, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\http\client.py", line 1277, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\http\client.py", line 1037, in _send_output self.send(msg) File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\http\client.py", line 975, in send self.connect() File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\http\client.py", line 1454, in connect self.sock = self._context.wrap_socket(self.sock, File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\ssl.py", line 513, in wrap_socket return self.sslsocket_class._create( File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\ssl.py", line 1071, in _create self.do_handshake() File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\ssl.py", line 1342, in do_handshake self._sslobj.do_handshake() ssl.SSLError: [SSL: WRONG_SIGNATURE_TYPE] wrong signature type (_ssl.c:997) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 15, in <module> File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 241, in urlretrieve with contextlib.closing(urlopen(url, data)) as fp: File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 216, in urlopen return opener.open(url, data, timeout) File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 519, in open response = self._open(req, data) File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 536, in _open result = self._call_chain(self.handle_open, protocol, protocol + File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 496, in _call_chain result = func(*args) File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 1391, in https_open return self.do_open(http.client.HTTPSConnection, req, File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\urllib\request.py", line 1351, in do_open raise URLError(err) urllib.error.URLError: <urlopen error [SSL: WRONG_SIGNATURE_TYPE] wrong signature type (_ssl.c:997)> >>> # 구글이미지+큰거 다운로드 import imp from lib2to3.pgen2 import driver from tkinter import BROWSE 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 os import urllib.request # url 이미지 다운로드 라이브러리 import pyautogui # 크롬 드라이버 자동 업데이트 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) if not os.path.exists("파이썬/고양이"): os.mkdir("파이썬/고양이") url = "https://www.google.com/search?q=%EA%B3%A0%EC%96%91%EC%9D%B4&prmd=ivsn&sxsrf=ALiCzsZMlAb_fB1ieepQcfla0HAFPCSjlQ:1658683173264&source=lnms&tbm=isch&sa=X&ved=2ahUKEwjD-diqhJL5AhUE-2EKHVGcChoQ_AUoAXoECAIQAQ&biw=819&bih=862&dpr=2" browser.implicitly_wait(10) browser.maximize_window() browser.get(url) # 무한 스크롤: 동적 사이트에서 자동으로 스크롤을 가장 아래까지 내려주는 알고리즘 # 스크롤을 내리기 전 기본이 되는 높이를 설정 before_h = browser.execute_script('return window.scrollY') while True: # 맨 아래로 스크롤을 내린다. browser.find_element(By.CSS_SELECTOR, 'body').send_keys(Keys.END) # 대부분의 웹페이지는 body 태그가 다 있다. 이걸 이용하고, END를 통해 맨 아래까지 스크롤 내림 # 너무 빠르면 오류가 생기니까 스크롤 사이에 페이지 로딩 시간을 주자. time.sleep(1) # 스크롤 후 높이 after_h = browser.execute_script('return window.scrollY') if after_h == before_h: break before_h = after_h # 이미지 태그를 추출하자 imgs = browser.find_elements(By.CSS_SELECTOR, ".rg_i.Q4LuWd") for i, img in enumerate(imgs, 1): img.click() time.sleep(1) # 큰 이미지 주소 추출 if i == 1: target = browser.find_elements(By.CSS_SELECTOR, "img.n3VNCb")[0] else: target = browser.find_elements(By.CSS_SELECTOR, "img.n3VNCb")[1] img_src = target.get_attribute("src") # HTTP Error 403: Forbidden opener = urllib.request.build_opener() opener.addheaders = [("User-Agent", "Mozila/5.0")] urllib.request.install_opener(opener) # 이미지 다운로드 urllib.request.urlretrieve(img_src, f"파이썬/고양이/{i}.jpg")
- 미해결이것이 진짜 크롤링이다 - 실전편
마지막 페이지 오류 + class 명 오류
안녕하십니까 선생님 최근에 마지막 페이지 오류를 해결하는 방법을 질문드렸는데, 친절히 답변주셔서 감사합니다. 수정해주신 코드로는 크롤링이 정상적으로 작동이 되는 것을 확인했습니다. 강사님께서 수정해주신 버튼 html 코드는 다음과 같습니다. isLastPage = soup.select_one('a.btn_next').attrs['aria-disabled'] 그러나, 1 of 3. 네이버에 "미옹이"를 검색한 다음, 페이지를 이동하는 버튼의 html을 보면, btn_next라는 class는 사진에 보이듯이 하나밖에 없고, 하나밖에 없는 해당 태그는 a가 아니라 button으로 나옵니다.어느 부분에서 강사님께서는 해당 태그가 a태그로 판단하신 것인지 궁금합니다.button 위에 있는 a태그는 옆으로 이동하는 버튼의 태그가 아니라, 1페이지, 2페이지의 a태그여서 버튼과는 관계없다고 생각합니다. # 네이버 "미옹이" 검색결과의 html 2 of 3. class 명을 일부만 적는 것이 이해되지 않습니다. 강사님께서 미옹이의 코드를 작성하실 때, class가 btn_next dimmed임에도 불구하고, btn_next만 명령어에 입력하셨습니다. 마찬가지로, 위 사진에 나와 있는 네이버 지도 크롤링 과정에서도 class 태그 4개 중에 input_search만 명령어에 입력하셨는데, search = browser.find_element(By.CSS_SELECTOR, "input.input_search") 전체 class인 input.input_search.ng-valid.ng-dirty.ng-touched를 입력하면 오류가 발생합니다. search = browser.find_element(By.CSS_SELECTOR, "input.input_search.ng-valid.ng-dirty.ng-touched") input.input_search와 input.input_search.ng-valid.ng-dirty.ng-touched 모두 html 상에서 검색했을 때 동일하게 1 of 1이 뜨는것을 확인했는데도 왜 전체 class태그를 입력한 것에서 오류가 발생하는지 궁금합니다. 정리하자면, class 태그를 full로 완전히 입력할때는 오류가 뜨더니(input.input_search.ng-valid.ng-dirty.ng-touched), class의 일부인 input.input_search를 넣으면 오류가 뜨지 않습니다. 따라서 어느 상황에서 class를 일부만 사용하고, 또는 전체를 사용해야 하는지 판단하는데 어려움이 있습니다. 아래는 발생하는 오류입니다. >>> search = browser.find_element(By.CSS_SELECTOR, "input.input_search.ng-valid.ng-dirty.ng-touched") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 857, in find_element return self.execute(Command.FIND_ELEMENT, { File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 435, in execute self.error_handler.check_response(response) File "C:\Users\rnrxh\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 247, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"input.input_search.ng-valid.ng-dirty.ng-touched"} (Session info: chrome=103.0.5060.134) Stacktrace: Backtrace: Ordinal0 [0x00575FD3+2187219] Ordinal0 [0x0050E6D1+1763025] Ordinal0 [0x00423E78+802424] Ordinal0 [0x00451C10+990224] Ordinal0 [0x00451EAB+990891] Ordinal0 [0x0047EC92+1174674] Ordinal0 [0x0046CBD4+1100756] Ordinal0 [0x0047CFC2+1167298] Ordinal0 [0x0046C9A6+1100198] Ordinal0 [0x00446F80+946048] Ordinal0 [0x00447E76+949878] GetHandleVerifier [0x008190C2+2721218] GetHandleVerifier [0x0080AAF0+2662384] GetHandleVerifier [0x0060137A+526458] GetHandleVerifier [0x00600416+522518] Ordinal0 [0x00514EAB+1789611] Ordinal0 [0x005197A8+1808296] Ordinal0 [0x00519895+1808533] Ordinal0 [0x005226C1+1844929] BaseThreadInitThunk [0x75C96739+25] RtlGetFullPathName_UEx [0x77A28FEF+1215] RtlGetFullPathName_UEx [0x77A28FBD+1165] >>> search.click() Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'search' is not defined >>> time.sleep(1) >>> # 검색어 입력 >>> >>> search.send_keys("강남역 맛집") Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'search' is not defined >>> search.send_keys(Keys.ENTER) # 검색어를 입력하고, 엔터를 치라는 명령어 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'search' is not defined >>> time.sleep(2) 아래는 제가 작성한 코드입니다. # 셀레니움 기본설정 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 # 크롬 드라이버 자동 업데이트 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.ng-valid.ng-dirty.ng-touched") search.click() time.sleep(1) # 검색어 입력 search.send_keys("강남역 맛집") search.send_keys(Keys.ENTER) # 검색어를 입력하고, 엔터를 치라는 명령어 time.sleep(2) 3 of 3. 왜 id를 사용하지 않으셨는지 궁금합니다. 사진에는 class 뿐만 아니라 해당 태그의 고유값인 id도 있습니다. 그러나, id를 사용하기 위해 아래와 같이 copy selector를 입력했음에도 불구하고 오류가 발생합니다. search = browser.find_element(By.CSS_SELECTOR, "#input_search1658797242706") 긴 질문 읽어주셔서 정말 감사합니다.
- 미해결이것이 진짜 크롤링이다 - 실전편
마지막 페이지 오류
안녕하십니까, 크롤링 강의 잘 듣고 있습니다. 마지막 페이지를 찾는 과정에 궁금한 점이 있어 질문드립니다. 첫째, 마지막 페이지에서 비활성화된 버튼의 html을 보시면, 강의 내용과 다르게 a태그가 아니라 button에 들어가있습니다. 둘째, islastpage = ........... 부분을 넣지 않으면 크롤링이 제대로 되는데, 해당 부분을 추가하면 세번째 사진의 오류가 발생합니다. 셋째, no attribute 'attrs'를 어떻게 해결할지 방법이 궁금합니다. 아래는 작성된 명령어입니다. from sqlite3 import Row import requests from bs4 import BeautifulSoup import time import pyautogui from openpyxl import Workbook from openpyxl.styles import Alignment # 여러 페이지 가져오기 # 키워드 keyword = pyautogui.prompt("검색어를 입력하세요") lastpage = int(pyautogui.prompt("몇 페이지까지 크롤링 할까요?")) # pyautogui.prompt는 문자열인 결과를 뽑아내는데, 페이지는 숫자니까 int로 묶어서 문자를 숫자로 바꿔주자. # 엑셀 생성하기 wb = Workbook() # 엑셀 시트 생성 ws = wb.create_sheet(keyword) # 열 너비 조절: 크롤링한 결과에 비해 각 행이 너무 좁으니까 조절하자 ws.column_dimensions["A"].width = 60 ws.column_dimensions["B"].width = 60 ws.column_dimensions["C"].width = 120 # 행 번호 row = 1 page_num = 1 # 첫번째 반복을 돌 때는 page_num가 1이다. for i in range(1, lastpage*10, 10): # 네이버 기사는 10 단위로 변한다! print(f"{page_num}페이지 크롤링 중입니다============================") response = requests.get(f"https://search.naver.com/search.naver?sm=tab_hty.top&where=news&query={keyword}&start={i}") # 페이지 파라미터는 query 뒤에 &start={i}를 넣어주면 된다. html = response.text soup = BeautifulSoup(html, "html.parser") articles = soup.select("div.info_group") # 뉴스 기사 중 div가 info_group인 것을 선택해라. # info_group이 총 몇개인지 확인하니까, word에 나와 있듯이 총 기사가 10개임을 확인했다. for article in articles: links = article.select("a.info") # article의 a태그 중 class가 info인 녀석들을 가져오자. if len(links) >= 2: # 가져온 결과값은 리스트 형태이고, word에 나와 있듯이 네이버 뉴스는 a태그 2개로 구성되어 있다. 따라서 links의 리스트 중 len함수를 통해 리스트가 몇개인지 파악하고, 링크가 2개 이상인지 확인한다. url = links[1].attrs["href"] # 우리가 가져올 건 link 중 2번째 요소니까, [1]을 입력한다(리스트 인덱스는 0부터 시작하니까!) # 2. 네이버 뉴스 본문 내용 가져오기 response = requests.get(url, headers={'User-agent' : 'Mozila/5.0'}) # 방금 만든 url에 다시 requests를 사용!, 봇으로 인식되는걸 피하기 위한 header도 넣자. html = response.text soup_sub = BeautifulSoup(html, "html.parser") # 만약 연예 뉴스 라면 if "entertain" in response.url: # 이때, response.url이 아니라 그냥 url만 적으면 "리다이렉션"으로 인한 오류가 발생한다. 그러니까, 위에 만들어 놓은 response 객체의 url을 가져오자. title = soup_sub.select_one(".end_tit") # 연예 뉴스 타이틀은 class="end_tit"로 표시됨 content = soup_sub.select_one("#articeBody") # 연예뉴스 본문의 id는 articeBody elif "sports" in response.url: title = soup_sub.select_one("h4.title") content = soup_sub.select_one("#newsEndContents") # 본문 내용 안의 불필요한 div와 p 삭제 divs = content.select("div") # select의 결과는 리스트 형태니까 for문을 쓸 수 있다. for div in divs: div.decompose() # div를 없애라는 명령어! paragraphs = content.select("p") for paragraph in paragraphs: paragraph.decompose() else: # 연예 기사가 아니라면 기존에 작성한 뉴스의 id를 사용해라! title = soup_sub.select_one(".media_end_head_title") content = soup_sub.select_one("#newsct_article") # 네이버뉴스의 본문을 모두 포함하는 것은 id ct 이다. # 그냥 print(content.text)만 입력해도 결과가 나오지만, 좀 정리해보자 print("==================링크==================\n", url) # \n은 한줄 띄운다는 뜻이다. print("==================제목==================\n", title.text.strip()) # 문자열 양쪽의 공백은 strip()로 없앨 수 있다. print("==================본문==================\n", content.text.strip()) # 출력결과를 저장하자. # 그런데, 출력결과는 기사1은 A1행, 기사2는 A2행 등 뒤의 숫자가 자꾸 변해야 한다 # 따라서, 크롤링을 시작하기 전에, 행 번호를 변수로 처리해주자. ws[f"A{row}"] = url ws[f"B{row}"] = title.text.strip() ws[f"C{row}"] = content.text.strip() # 자동 줄바꿈 기능(엑셀에서 한줄로만 길게 나타나는게 아니라, 자동으로 줄을 바꿔준다) ws[f"C{row}"].alignment = Alignment(wrap_text=True) row = row + 1 time.sleep(0.3) # 페이지를 추가하기 전에, 마지막 페이지 여부를 확인하자 islastpage = soup.select_one(".btn_next dimmed").attrs["aria-disabled"] if islastpage == "true": print("마지막 페이지 입니다") break page_num = page_num + 1 wb.save(f"{keyword}_result.xlsx")
- 해결됨이것이 진짜 크롤링이다 - 실전편
검색되는 페이지의 수와 크롤링 되는 페이지의 수가 다른 경우
안녕하세요. 강의에서 보여주신 코드와 예제로 들어주시는 '미옹이'를 이용하여 5페이지까지 크롤링 하였으나 현재 네이버에서 검색되는 미옹이와 관련된 기사가 3페이지까지 있음에도 불구하고 저는 5페이지까지 모두 크롤링 되는 것으로 확인된 거 같습니다. 이와 동시에 '마지막 페이지 입니다.'라는 문구는 제 결과창에 확인할 수가 없었습니다.. 이런 경우에는 어떤 곳에 수정을 해야지 강의에서 와 같은 화면을 제가 접하게 될 수 있을까요? 감사합니다.
- 해결됨이것이 진짜 크롤링이다 - 실전편
href 가져오기
안녕하십니까 강사님 아래는 강의에 나온 href 속성을 가져오는 명령문인데,어떤 경우에는 get.attribute를 사용하고, 어떤 경우에는 attrs를 사용합니다. 강의 중에 "이건 리스트 형태로 나오니까...."와 같은 말씀을 하시면서 attrs를 사용하셨는데,어떤 경우에 리스트로 나오는 것을 파악하고 attrs 또는 get.attribute를 써야 하는지 이해하기 어렵습니다. link = item.find_element(By.CSS_SELECTOR, '#__next > div > div.style_container__1YjHN > div.style_inner__18zZX > div.style_content_wrap__1PzEo > div.style_content__2T20F > ul > div > div:nth-child(1) > li > div > div.basicList_info_area__17Xyo > div.basicList_title__3P9Q7 > a').get_attribute('href') print(name, price, link) 2. for article in articles: links = article.select("a.info") if len(links) >= 2: url = links[1].attrs["href"]
- 해결됨이것이 진짜 크롤링이다 - 실전편
네이버 뉴스 본문 링크 질문
안녕하십니까,뉴스본문 기사 크롤링 중 질문이 있습니다. 첨부사진을 보시면, 첫번째 a태그의 class가 info press인데,명령어를 입력하실 때 그냥 links = article.select("a.info")로 info만 입력하셨습니다. 띄어쓰기 전의 한 단어만 class 명으로 보는 것인지 궁금합니다. 아래는 강사님을 따라한 코드입니다(크롤링 결과는 잘 나옴) # 1. 삼성전자를 검색하고, 네이버 뉴스 본문의 링크만 가져온다 response = requests.get("https://search.naver.com/search.naver?where=news&sm=tab_jum&query=%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90") html = response.text soup = BeautifulSoup(html, "html.parser") articles = soup.select("div.info_group") # 뉴스 기사 중 div가 info_group인 것을 선택해라. # info_group이 총 몇개인지 확인하니까, word에 나와 있듯이 총 기사가 10개임을 확인했다. for article in articles: links = article.select("a.info") # article의 a태그 중 class가 info인 녀석들을 가져오자. if len(links) >= 2: # 가져온 결과값은 리스트 형태이고, word에 나와 있듯이 네이버 뉴스는 a태그 2개로 구성되어 있다. 따라서 links의 리스트 중 len함수를 통해 리스트가 몇개인지 파악하고, 링크가 2개 이상인지 확인한다. url = links[1].attrs["href"] # 우리가 가져올 건 link 중 2번째 요소니까, [1]을 입력한다(리스트 인덱스는 0부터 시작하니까!) # print(url) 본문 링크만 가져온다면 여기서 마치면 되지만, 우리가 원하는건 본문 내용이다. # 2. 네이버 뉴스 본문 내용 가져오기 response = requests.get(url, headers={'User-agent' : 'Mozila/5.0'}) # 방금 만든 url에 다시 requests를 사용!, 봇으로 인식되는걸 피하기 위한 header도 넣자. html = response.text soup = BeautifulSoup(html, "html.parser") # print(soup)를 통해 제대로 본문을 가져오는지 확인해보자 content = soup.select_one("#newsct_article") # 네이버뉴스의 본문을 모두 포함하는 것은 id newsct_article 이다. print(content.text)
- 미해결이것이 진짜 크롤링이다 - 실전편
URL 가져올 때 & 제거하는 이유
안녕하세요 네이버 금융 크롤링 - 여러페이지 가져오기 강의에서 처음에 URL 을 가져올 때 , page 앞에 & 를 제거하는 이유가 궁금합니다. 강의에는 설명이 없는 것 같아서요
- 미해결이것이 진짜 크롤링이다 - 실전편
강의 내용 외 크롤링 질문입니다.
1.엑셀 파일에 저장되어있는 url을 list 형식으로 가져온다. 2. 가져온 url들을 '상품' 열에 str형식으로 저장한다. 3. 가져온 url 에 접속하여 크롤링하여 해당 url 행에 각각의 컬럼에 해당하는 값을 저장한다. 위의 3개의 과정을 코드로 작성해보았는데 작동이 되질 않아 뭐가 문제인지 잘 모르겠습니다 ㅠㅠ import requests from bs4 import BeautifulSoup import time import openpyxl import pandas as pd import numpy as np import os #url 추출 excel_source = pd.read_excel('example_2.xlsx') df=pd.DataFrame(excel_source) url = df['상품'] item_url = list(url) for i in item_url: response = requests.get(i) html = response.text soup = BeautifulSoup(html, 'html.parser') wb = openpyxl.Workbook() ws = wb.create_sheet("네이버쇼핑크롤링") ws.append(["상품", "썸네일", "상품명","카테고리","소비자가","판매가","배송비","리뷰수","사용자총평점","상품정보","상품번호","제조사","모델명","원산지","상품상태","브랜드","제조일자","판매자정보","상호명","사업자등록번호","사업장소재지","대표자","통신판매업번호"]) infos = soup.select("div._2-I30XS1lA ") for s in range(0,len(item_url)+1): ws.append([item_url[s]]) for z,info in enumerate(infos,1): #상품 #썸네일 #상품명 item_name = info.select_one("div.CxNYUPvHfB").text ws.append([z,df,item_name]) wb.save("naver_store.xlsx")
- 해결됨이것이 진짜 크롤링이다 - 실전편
맥에서 pyperclip, pyautogui 오류
안녕하세요. 영상을 보면서 코드를 입력하고 여러차례 시도해보았으나 안타깝게도 아이디와 비밀번호를 입력할 때, 제가 입력한 아이다와 비밀번호를 입력하지 않고 'v'라는 문자만 계속해서 입력되고 있습니다. 이 점을 해결하기 위해서는 어떤식으로 접근하는 게 좋은 방법일까요? 코드가 있는 창에는 제 실제 아이디와 비밀번호가 아닌 '아이디' 그리고 '비밀번호'라고 입력했습니다.
- 미해결이것이 진짜 크롤링이다 - 실전편
섹션 0. '강의소개 _ 셀레니움 ver 4.0 가이드 + 크롬 드라이버 자동으로 다운 받는 법' 에러!
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요! 선생님 강의를 너무너무 즐겁고 유익하게 듣고있는 수강생입니다! 강의소개 _ 셀레니움 ver 4.0 가이드 + 크롬 드라이버 자동으로 다운 받는 법' 해당 강의를 따라서 해보는 도중에 아래와 같이 에러가 계속 발생해서요! 혹시 무엇이 문제일까요.. ㅠ - 입력 코드 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome.options import Options #크롬 드라이버 자동 업데이트 from webdriver_manager.chrome import ChromeDriverManager service = Service(executable_path=ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) # 웹페이지 해당 주소 이동 driver.get("https://www.naver.com") - 입력 코드 D:\study\stratcoding\chapster02> cmd /C "C:\Users\lotte\AppData\Local\Programs\Python\Python310\python.exe c:\Users\lotte\.vscode\extensions\ms-python.python-2022.10.0\pythonFiles\lib\python\debugpy\adapter/../..\debugpy\launcher 57671 -- "d:\study\stratcoding\chapster02\10. 셀레니움_기본설정\10.셀레니움_기본설정.py" " [WDM] - ====== WebDriver manager ====== 2022-07-11 16:15:23,877 INFO ====== WebDriver manager ====== Traceback (most recent call last): File "d:\study\stratcoding\chapster02\10. 셀레니움_기본설정\10.셀레니움_기본설정.py", line 10, in <module> service = Service(executable_path=ChromeDriverManager().install()) File "C:\Users\lotte\AppData\Local\Programs\Python\Python310\lib\site-packages\webdriver_manager\chrome.py", line 38, in install driver_path = self._get_driver_path(self.driver) File "C:\Users\lotte\AppData\Local\Programs\Python\Python310\lib\site-packages\webdriver_manager\core\manager.py", line 29, in _get_driver_path binary_path = self.driver_cache.find_driver(driver) File "C:\Users\lotte\AppData\Local\Programs\Python\Python310\lib\site-packages\webdriver_manager\core\driver_cache.py", line 95, in find_driver driver_version = driver.get_version() File "C:\Users\lotte\AppData\Local\Programs\Python\Python310\lib\site-packages\webdriver_manager\core\driver.py", line 43, in get_version self.get_latest_release_version() File "C:\Users\lotte\AppData\Local\Programs\Python\Python310\lib\site-packages\webdriver_manager\drivers\chrome.py", line 37, in get_latest_release_version self.browser_version = get_browser_version_from_os(self.chrome_type) File "C:\Users\lotte\AppData\Local\Programs\Python\Python310\lib\site-packages\webdriver_manager\core\utils.py", line 152, in get_browser_version_from_os cmd_mapping = { KeyError: 'google-chrome'
- 미해결이것이 진짜 크롤링이다 - 실전편
7월 중에 추가 되는 강의(강의 수강 기간)
제가 7월에 강의 만료 되는데 7월에 강의 새롭게 추가되면 강의 수강 기간 연장 가능할까요..? 아니면 추가입금하면 강의 수강 기간 무제한으로 늘릴 수 있는 방법이 있나요?
- 미해결이것이 진짜 크롤링이다 - 실전편
Import error 해결이 어려워 질문드립니다.
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요 좋은 강의 항상 잘 듣고 있습니다. 다름아니라, 아래와 같은 에러가 나타납니다. ImportError: cannot import name 'webdrvier' from 'selenium' (/Users/taehwa/opt/anaconda3/lib/python3.9/site-packages/selenium/__init__.py) 비쥬얼스튜디오코드에서 코드 돌렸으나 가상환경(아나콘다)환경 기반이라 에러가 나는 것 같은데 아나콘다에도 selenium과 webdriver_manager를 설치하였음에도 위와 같은 에러메세지가 나옵니다. 파일명도 10.셀레니움 환경설정. py로 파일명도 selenium.py 로 쓰지 않았음에도 importerror를 해결할 수 없어 문의드립니다.
- 미해결이것이 진짜 크롤링이다 - 실전편
네이버 뉴스의 날짜를 수집하고자 합니다.
안녕하세요. FW 시즌 vs SS 시즌별로 피부 고민의 차이를 좀 분석해볼려고 하고요. 네이버 뉴스 크롤링 코드에서 날짜 부문을 추가해서 수집하려고 하는 데 오류가 발생하는 상황입니다. 날짜 HTML은 제대로 불러오는 것 같은데요... 출력에서 조금만 검토해주셨으면 하는 부분이 있습니다. 제가 추가로 작성한 부분은 빨간색으로 색칠해두었습니다. ------------------------------------------------------------------------------------------------------------------------ keyword = pyautogui.prompt("검색어를 입력하세요.") lastpage = pyautogui.prompt("마지막 페이지번호를 입력하세요.") # 엑셀 생성 wb = Workbook() ws = wb.create_sheet(keyword) # 행번호 row = 1 # 열 너비 조절 ws.column_dimensions['A'].width = 60 ws.column_dimensions['B'].width = 60 ws.column_dimensions['C'].width = 120 page_num = 1 for i in range(1, int(lastpage)*10, 10): print(f"{page_num}페이지 크롤링 중입니다.") response = requests.get(f"https://search.naver.com/search.naver?where=news&sm=tab_jum&query={keyword}&start={i}") html = response.text soup = BeautifulSoup(html, 'html.parser') articles = soup.select("div.info_group") # 뉴스 기사 div 10개 추출 for article in articles: links = article.select("a.info") if len(links) >= 2: # 링크가 2개 이상이면 url = links[1].attrs['href'] # 두번째 링크의 href 추출 # 다시 request를 날려 준다 response = requests.get(url, headers={'User-Agent' : 'Mozila/5.0'}) html = response.text soup_sub = BeautifulSoup(html, 'html.parser') # 연예 뉴스 체크 if "entertain" in response.url: title = soup_sub.select_one(".end_tit") content = soup_sub.select_one("#articeBody") date = soup_sub.select_one("div.article_info > span > em") else: title = soup_sub.select_one(".media_end_head_headline") content = soup_sub.select_one("#newsct_article") date = soup_sub.select_one("span.media_end_head_info_datestamp_time._ARTICLE_DATE_TIME") print("=======링크======= \n", url) print("=======제목======= \n", title.text.strip()) print("=======본문======= \n", content.text.strip()) print("=======날짜======= \n", date) # w저장 ws[f'A{row}'] = url ws[f'B{row}'] = title.text.strip() ws[f'C{row}'] = content.text.strip() ws[f'D{row}'] = date.text.strip() # 자동 줄바꿈 기능 ws[f'C{row}'].alignment = Alignment(wrap_text=True) row = row + 1 time.sleep(0.3) # 마지막 페이지 여부 확인하기 isLastPage = soup.select_one("a.btn_next").attrs['aria-disabled'] if isLastPage == 'true': print("마지막 페이지입니다.") break page_num = page_num + 1 # 워드 문서 저장하기 wb.save(f"{keyword}_result.xlsx") ============================================================================================ =======날짜======= <span class="media_end_head_info_datestamp_time _ARTICLE_DATE_TIME" data-date-time="2022-06-05 09:42:02">2022.06.05. 오전 9:42</span>출력이 이렇게되는 데요. 2022.06.05. 오전 9:42만 받아보게끔 하는 방법이 있을까요?