* 브라우저를 띄우지 않고 메모리에만 selenium을 띄워 크롤링하기
- 기존 코드( https://blog.himion.com/176 )와 거의 유사하다.
- headlessDriver() 함수가 추가되었다
'''
* 구글 이미지 가져오기 ver. Headless
'''
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import undetected_chromedriver as uc
import urllib
import time, datetime
ITEM_LIST = [ "Keith Thompson", "Zdzislaw Beksinski", "dariusz zawadzki"] # 1번
FOLDER = 'google' # 2번
IMG_XPATH = '//*[@id="Sva75c"]/div[2]/div/div[2]/div[2]/div[2]/c-wiz/div/div/div/div[3]/div[1]/a/img[1]' # 3번
SIGNINURL = 'https://accounts.google.com/signin/v2/identifier?hl=ko&passive=true&continue=https%3A%2F%2Fwww.google.com%2F&ec=GAZAmgQ&flowName=GlifWebSignIn&flowEntry=ServiceLogin'
ID = 'xxxx@gmail.com' # 4번
PASSWORD = 'xxxx' # 5번
def main():
start = check_start() # 시간 측정 시작
driver = headlessDriver()# headless를 적용하고 싶을때
driver.get(SIGNINURL)
googleSignIn(driver)# 구글로그인하고
for searchItem in ITEM_LIST:
saveDir = makeFolder(searchItem)
url = makeUrl(searchItem)# 검색할 url 가져와서
driver.get(url)# 이미지 검색으로 가서
maximizeWindow(driver)# 창최대화
scrollToEnd(driver)
forbiddenCount = saveImgs(driver, saveDir, start)# 모든 상세 이미지 src들을 가져온다
sec = check_time(start)
print(f'실패수{str(forbiddenCount)}, {sec}, {datetime.datetime.now().time()}')
time.sleep(10)
driver.quit()
def headlessDriver():
options = uc.ChromeOptions()
options.headless=True
options.add_argument('--headless=new')
driver = uc.Chrome(options=options)
return driver
# 구글 로그인
def googleSignIn(driver):
idBtn = driver.find_element(By.XPATH,'//*[@id="identifierId"]')# id 입력칸
idBtn.send_keys(ID)
nextBtn = driver.find_element(By.XPATH,'//*[@id="identifierNext"]/div/button')
nextBtn.click()# 다음 버튼 클릭
# 아래 코드는 비밀번호 요소가 화면에 나타날때가지 10초간 기다리는 코드이나
# 비번의 경우 not interactive elem라서 에러가 뜬다. 하지만 돌아가는 코드이니 기다림이 필요할때 쓰자.
try:
passwordBtn = WebDriverWait(driver, timeout=10).until(EC.presence_of_element_located( (By.XPATH,'//*[@id="password"]/div[1]/div/div[1]/input') ))
time.sleep(4)
passwordBtn = driver.find_element(By.XPATH,'//*[@id="password"]/div[1]/div/div[1]/input')# 비밀번호 입력칸
passwordBtn.send_keys(PASSWORD)
passwordNextBtn = driver.find_element(By.XPATH,'//*[@id="passwordNext"]/div/button')
passwordNextBtn.click()# 비밀번호 다음 버튼
print('구글 로그인 성공')
# driver.implicitly_wait(10)
except OSError as e:
print(e)
time.sleep(20)# 휴대폰 본인 인증등의 시간이 충분히 필요하다
# 구글 이미지 검색 url 만들기
def makeUrl(searchItem):
url = 'https://www.google.com/search'
params ={# q와 tbm이 필수
'q' : searchItem,
'tbm' : 'isch',
}
url = url + '?' + urllib.parse.urlencode(params)
return url
# 폴더 생성
def makeFolder(searchItem):
saveDir = os.path.join(os.getcwd(), 'data', f'{FOLDER}_{searchItem}')
try:
if not(os.path.isdir(saveDir)): # 해당 폴더가 없다면
os.makedirs(os.path.join(saveDir)) # 만들어라
return saveDir
except OSError as e:
print(e+'폴더 생성 실패')
# 창 최대화
def maximizeWindow(driver):
driver.maximize_window()
# 모든 이미지 목록을 가져오기 위해 무한 스크롤 다운
def scrollToEnd(driver):
prev_height = driver.execute_script('return document.body.scrollHeight')
print(f'prev_height: {prev_height}')
while True:
time.sleep(1) #네이버는 sleep없이 이동할 경우 무한로딩에 걸린다.
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
time.sleep(3)
cur_height = driver.execute_script('return document.body.scrollHeight')
print(f'cur_height: {cur_height}')
if cur_height == prev_height:
print('높이가 같아짐')
break
prev_height = cur_height
# 페이지를 모두 로딩한 후에는 최상단으로 다시 올라가기
driver.execute_script('window.scrollTo(0, 0)')
# 모든 이미지들을 저장한다
def saveImgs(driver, saveDir, start):
time.sleep(1)
forbiddenCount = 0
imgs = driver.find_elements(By.CSS_SELECTOR, '.rg_i.Q4LuWd')
img_count = len(imgs)
print(f'전체 이미지수 : {img_count}')
# 하나씩 클릭해가며 저장
for imgNum, img in enumerate(imgs): # imgNum에 이미지번호가 0부터 들어간다
try:
img.click()
time.sleep(3)
# 아래의 xPath는 자주 바뀌는 것 같다. 나머지는 고정인거 같으니 이것만 가끔 확인해주자
bigImg = driver.find_element(By.XPATH, IMG_XPATH)
src = bigImg.get_attribute('src')
urllib.request.urlretrieve(src, saveDir + '/' + str(imgNum) + '.jpg')
sec = check_time(start)
print(f'{imgNum+1}/{img_count} saved {sec}')
except Exception as e:
print(e)
forbiddenCount += 1# 저장 실패한 개수. forbidden이나 파일에러도 꽤 많다
continue
return forbiddenCount
# 시간 측정
def check_start():
start_time = time.time()
print("Start! now.." + str(start_time))
return start_time
def check_time(start):
end = time.time()
during = end - start
sec = str(datetime.timedelta(seconds=during)).split('.')[0]
return sec
main()
'그 밖에 AI > 데이터 준비하기' 카테고리의 다른 글
[Crawling] ip우회해 크롤링하기 ver. 펨코 (1) | 2023.07.05 |
---|---|
[Crawling] 구글 로그인하고 이미지 가져오기 - 로라 이미지 수집 (0) | 2023.06.20 |
[Crawling] 네이버 이미지 가져오기 - 로라 이미지 수집 (11) | 2023.06.19 |
Extracting text from epub with python - 파이썬으로 epub에서 텍스트 뽑기 (0) | 2023.04.03 |
기상청 지진 정보 크롤링 (0) | 2017.12.01 |