0
import os
import sys
import urllib.request
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from time import sleep
from bs4 import BeautifulSoup

keyword = input('검색어 : ')
maxImages = int(input('다운로드 시도할 최대 이미지 수 : '))

# 프로젝트에 미리 생성해놓은 crawled_img폴더 안에 하위 폴더 생성
# 폴더명에는 입력한 키워드, 이미지 수 정보를 표시함
path = 'crawled_images/'+keyword+'_'+str(maxImages)

try:
    # 중복되는 폴더 명이 없다면 생성
    if not os.path.exists(path):
        os.makedirs(path)
    # 중복된다면 문구 출력 후 프로그램 종료
    else:
        print('이전에 같은 [검색어, 이미지 수]로 다운로드한 폴더가 존재합니다.')
        sys.exit(0)
except OSError:
    print ('os error')
    sys.exit(0)

pages = int((maxImages-1)/100)+1 #한 페이지당 표시되는 이미지 수(100)을 참고하여 확인할 페이지 수 계산
imgCount = 0 # 추출 시도 이미지 수
success = 0 # 추출 성공 이미지 수
finish = False # 이미지에 모두 접근했는지 여부

# 크롬 드라이버 설정
# (크롤링할 때 웹 페이지 띄우지 않음, gpu 사용 안함, 한글 지원, user-agent 헤더 추가)
service = Service(executable_path='chromedriver')
options = webdriver.ChromeOptions()
#options.add_argument('headless')
options.add_argument('--disable-gpu')
options.add_argument('lang=ko_KR')
options.add_argument("user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36")
driver = webdriver.Chrome(service=service,options=options)

for i in range(1,int(pages)+1):
    #웹 페이지 접근 후 1초동안 로드를 기다림
    driver.get('https://pixabay.com/images/search/'+keyword+'/?pagi='+str(i))
    sleep(1)

    #크롤링이 가능하도록 html코드 가공
    html = driver.page_source
    soup = BeautifulSoup(html,'html.parser')

    imgs = soup.select('div.verticalMasonry--RoKfF.lg--v7yE8 img') #요소 선택

    #마지막 페이지 여부 결정
    lastPage=False
    if len(imgs)!=100:
        lastPage=True

    #5번 제목에서 설명함
    for img in imgs:

        srcset = ""
        a = img.get('src')
        b = img.get('srcset')
        c = img.get('data-lazy-srcset')
        d = img.get('data-lazy-src')
        if a is not None:
            srcset = a
        elif b is not None:
            srcset = b
        elif c is not None:
            srcset = c
        else:
            srcset = d

        src = ""
        if len(srcset):
            src = str(srcset).split()[0] #가장 작은 사이즈의 이미지 경로 추출
            print(src)
            filename = src.split('/')[-1] #이미지 경로에서 날짜 부분뒤의 순 파일명만 추출
            print(filename)
            saveUrl = path+'/'+filename #저장 경로 결정
            print(saveUrl)
            

            #if src.startswith('http') or src.startswith('https'):
                #파일 저장
                #user-agent 헤더를 가지고 있어야 접근 허용하는 사이트도 있을 수 있음(pixabay가 이에 해당)
            req = urllib.request.Request(src, headers={'User-Agent': 'Mozilla/5.0'})
            try:
                imgUrl = urllib.request.urlopen(req).read() #웹 페이지 상의 이미지를 불러옴
                with open(saveUrl,"wb") as f: #디렉토리 오픈
                    f.write(imgUrl) #파일 저장
                success+=1
            except urllib.error.HTTPError as e:
                print('에러 발생:', e)
                sys.exit(0)
            #else:
            #    print('유효하지 않은 이미지 URL:', src)

        imgCount+=1

        if imgCount==maxImages:
            finish = True #입력한 이미지 수 만큼 모두 접근했음을 알림
            break
    
    #finish가 참이거나 더 이상 접근할 이미지가 없을 경우 크롤링 종료
    if finish or lastPage:
        break

print('성공 : '+str(success)+', 실패 : '+str(maxImages-success))

website is pixabay. I think img.get('src') have blank.gif so i may be to get the url error. but when I delete the img.get('src') i got the other error. it is len(srcset) has None type error. i many tried other way but i didn't get to slove. please help me... if you reslove this problem, i appreciate you.

thank you !

김도열
  • 11
  • 1

2 Answers2

0

ValueError: unknown url type: '/static/img/blank.gif' means the whole url you gave there is '/static/img/blank.gif'. That's not url, that's relative path and browsers normally add protocol and domain to them.

So instead of just passing src into request, you should first check if there's base url there and if not, add it manually. Something along the lines of

if not src.startswith(("https://", "http://")):
    src = f"https://pixabay.com/{src}"

Now, your 'fix' was just to remove line that gave you that value, and then you got another error. So let's look what would cause srcset to be None:

        srcset = ""
        a = None  # you said you removed img.get('src') part
        b = img.get('srcset')
        c = img.get('data-lazy-srcset')
        d = img.get('data-lazy-src')
        if a is not None:
            srcset = a
        elif b is not None:
            srcset = b
        elif c is not None:
            srcset = c
        else:
            srcset = d

        src = ""
        if len(srcset):

We have checks is not None... but there's no check for d is not None! So it all a, b, c are None, srcset will NOT have the "default" empty string you tried to use before all those img.get but whatever is in d - and it can be None. That's all.

If you change else into elif d is not None, it will correctly skip that assignment and your srcset will be ""

h4z3
  • 5,265
  • 1
  • 15
  • 29
  • thank u for ur answer ! but I have other problem. image can't be downloaded. I changed to elif d is not None. and I add the base url. like this, – 김도열 Jul 07 '23 at 01:49
  • ``` if not src.startswith(("https://", "http://")): src = f"https://pixabay.com/{src}" req = urllib.request.Request(src, headers={'User-Agent': 'Mozilla/5.0'}) try: imgUrl = urllib.request.urlopen(req).read() with open(saveUrl,"wb") as f: f.write(imgUrl) success+=1 except urllib.error.HTTPError as e: print('에러 발생:', e) sys.exit(0) ``` – 김도열 Jul 07 '23 at 01:49
-1

Could you do (x != None instead of x is not None): is check if two given objects are the same so using it might cause errors, it's better to check the equality instead.

TwoZed3
  • 64
  • 3
  • None is a singleton, all linters actually tell you to compare `is None`, `is True`, `is False` instead of `==` (or `!=`). (In case of True and False, 1==True and 0==False, so `is True/False` is actually *really* important, while in case of None it's mostly style recommendation - although you could have custom objects that e.g. always `==` to anything) – h4z3 Jul 06 '23 at 12:11