Python 3 인터넷 파충류:Scrapy 입문 사용 Images Pipline 사진 다운로드
지난 블 로 그 는 간단 한 실전 으로 scrapy 프레임 워 크 의 사용 을 익 혔 다.그러나 사진 을 다운로드 하 는 방법 은 requests 라 이브 러 리 를 사용 하고 scrapy 자체 가 사진 을 가지 고 다운로드 하 는 방법
ImagesPipline
을 사용한다.둘째,이미지 Pipline 를 처음 알 게 되 었 습 니 다.
1.Images Pipline 의 특성:
image_urls
(type=list)그룹 에 넣 으 세 요.item
파충류 에서 돌아 와 진입Item Piplines
.item
그룹 내image_urls
는 Scrapy 의 스케줄 러 와 다운로드 기(스케줄 러 와 다운로드 기의 미들웨어 를 재 활용 할 수 있다 는 뜻)에 의 해 다운로드 되 며,우선 순위 가 높 으 면 다른 페이지 에서 캡 처 되 기 전에 처리 된다.프로젝트 는 파일 의 다운로드 가 완료 되 거나 어떤 이유 로 다운로드 가 완료 되 지 않 을 때 까지 이 특정한 파이프 단계 에서'locker'상 태 를 유지 합 니 다.URLs
그룹 에서 얻 은)와 그림 의 검사 코드(checksum)등 사전 목록 을 포함 합 니 다.images 목록 의 파일 순 서 는 원본image_urls
그룹 과 일치 합 니 다.어떤 그림 을 다운로드 하 는 데 실패 하면 잘못된 정 보 를 기록 하고 그림 도 files 그룹 에 나타 나 지 않 습 니 다.3.ImagesPipline 사용 사례
정의 item
media pipeline 을 사용 하기 위해 서 는 사용 하기 만 하면 됩 니 다.이 어 spider 가'file'이 있 는 것 을 되 돌려 줍 니 다.urls'나'image 'urls'(Files 나 Images Pipeline 을 사용 하 는 것 에 달 려 있 음)키 의 dict 는 pipeline 에서 해당 하 는 결 과 를 추출 합 니 다.
Item 을 정의 하 는 item 에서 사용 하 는 것 을 더 좋아한다 면 필요 한 필드 를 설정 해 야 합 니 다.예 를 들 어 Image Pipeline 의 예 를 들 어:
import scrapy
class MyItem(scrapy.Item):
# ... other item fields ...
image_urls = scrapy.Field()
images = scrapy.Field()
여기 서 제 가 아 이 템 을 정 의 했 어 요.
import scrapy
class MscrapyItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
image_urls = scrapy.Field()
image_ids = scrapy.Field()
image_paths = scrapy.Field()
pass
설정 설정
우선 항목 에 추가 해 야 합 니 다
image_urls
ITEM_PIPELINES = {'scrapy.pipeline.images.ImagesPipeline': 1}
이 어
ITEM_PIPELINES
다운로드 한 그림 을 저장 하기 위해 유효한 폴 더 로 설정 했다.그렇지 않 으 면 파 이 프 는 ITEM 에 있어 도 사용 하지 않 습 니 다.PIPELINES 설정 에 추가 되 었 습 니 다.이미지 파이프라인 에 대한 설정
IMAGES_STORE
IMAGES_STORE = '/path/to/valid/dir'
미리 보기 그림 등 다른 속성 에 대해 서 는 공식 문 서 를 참조 할 수 있 습 니 다.
3.ImagePipline 그림 기본 다운로드 이름 수정
1.문서 판독
IMAGES_STORE
의 여러 속성 에서 특히 주의해 야 할 것 은 파일 시스템 저장 입 니 다.파일 저장 시의 기본 이름 을 정의 하기 때문에 그림 의 기본 이름 을 수정 하려 면 여기 서부 터 시작 해 야 합 니 다.파일 시스템 저장 소
파일 은 URL 의 SHA 1 hash 를 파일 이름 으로 합 니 다.
예 를 들 어 아래 그림 URL 에 대해 서 는...
http://www.example.com/image.jpg 그것 의 SHA 1 hash 값 은:
ImagePipline
다음 파일 로 다운 로드 됩 니 다:
3afec3b4765f8f0a07b78f98c07b83f013567a0a
그 중:
< IMAGES_STORE>/full/3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg
은
설정 에 정 의 된 폴 더>IMAGES_STORE
그림 과 미리 보기 그림 을 구분 하 는 키 폴 더 입 니 다.우 리 는 당연히 자신 이 다운로드 한 그림 의 이름 이 이해 할 수 없 는 숫자 라 는 것 을 원 하지 않 는 다.그래서 파일 이름 을 수정 해 야 합 니 다.
공식 문서 에서 다시 쓸 수 있 는 두 가지 방법 을 제공 합 니 다.
full
get_media_requests(item, info)
get_media_requests(item, info)
작업 프로 세 스에 서 볼 수 있 듯 이 파 이 프 는 파일 의 URL 을 얻 고 프로젝트 에서 다운로드 합 니 다.이렇게 하기 위해 서 는 재 작성
item_completed(results, items, info)
방법 이 필요 하 며,각 그림 URL 에 대해 서 는 Request 를 되 돌려 주어 야 합 니 다.def get_media_requests(self, item, info):
for file_url in item['file_urls']:
yield scrapy.Request(file_url)
, , 2- `item_completed()` :
get_media_requests()
: (success, file_info_or_error)
는 불 값 입 니 다.그림 이 성공 적 으로 다운로드 되 었 을 때success
입 니 다.어떤 이유 로 다운로드 에 실 패 했 습 니 다True
fileinfo_or_error 는 다음 키 워드 를 포함 하 는 사전(성공 하면False
또는 문제 가 발생 하면True
입 니 다.Twisted Failure
-파일 다운로드 url.요청 한 url 을url
방법 으로 되 돌려 줍 니 다.get_media_requests()
-이미지 저장 경로(FILES 와 유사)STORE)path
-그림 내용 MD5 hash itemcompleted()가 받 은 원 그룹 목록 은checksum
방법 으로 요청 한 순서 와 일치 하도록 보증 해 야 합 니 다.다음은 results 매개 변수의 전형 적 인 값 입 니 다.[(True, {'checksum': '2b00042f7481c7b056c4b410d28f33cf', 'path':
'full/0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg', 'url':
'http://www.example.com/files/product1.pdf'}), (False,
Failure(...))]
기본
get_media_requests()
방법 으로 되 돌아 갑 니 다get_media_requests()
.이 는 프로젝트 에 다운로드 할 파일 이 없다 는 것 을 의미 합 니 다.item_completed(results, items, info)
하나의 단독 항목 의 모든 그림 이 완료 되 었 을 때(다운 로드 를 완료 하거나 어떤 이유 로 다운로드 에 실 패 했 을 때)
None
방법 이 호출 됩 니 다.FilesPipeline.item_completed()
방법 은 출력 을 되 돌려 야 합 니 다.다음 프로젝트 파이프 단계 로 보 내 질 것 입 니 다.따라서 임의의 파이프 에서 한 것 처럼 항목 을 되 돌려 야 합 니 다.이것 은item_completed()
방법의 예 입 니 다.그 중에서 우리 가 다운로드 한 그림 경로(results 에 전송)를item_completed()
프로젝트 그룹 에 저장 합 니 다.만약 에 그림 이 없 으 면 우 리 는 항목 을 버 릴 것 입 니 다.from scrapy.exceptions import DropItem
def item_completed(self, results, item, info):
image_paths = [x['path'] for ok, x in results if ok]
if not file_paths:
raise DropItem("Item contains no files")
item['image_paths'] = image_paths
return item
기본 적 인 상황 에서
image_paths
방법 으로 되 돌아 갑 니 다item_completed()
.다음은 그림 파이프 의 완전한 예 입 니 다.그 방법 은 위 와 같 습 니 다.
import scrapy
from scrapy.pipeline.images import ImagesPipeline
from scrapy.exceptions import DropItem
class MyImagesPipeline(ImagesPipeline):
def get_media_requests(self, item, info):
for image_url in item['image_urls']:
yield scrapy.Request(image_url)
def item_completed(self, results, item, info):
image_paths = [x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem("Item contains no images")
item['image_paths'] = image_paths
return item
2.코드 실전
이전 블 로그 의 실전 데모 를 계속 하 겠 습 니 다.여기 서 piplines 의 코드 를 수정 하 였 습 니 다.
class UnsplashPipeline(ImagesPipeline):
def get_media_requests(self, item, info):
for image_url in item['image_urls']:
yield scrapy.Request(image_url)
def item_completed(self, results, item, info):
image_paths = [x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem("Item contains no images")
if item['image_ids']:
new_path = "full/"+item['image_ids'][0]+".jpg"
os.rename(settings.IMAGES_STORE+"/"+image_paths[0],settings.IMAGES_STORE+"/"+new_path)
item['image_paths'] = new_path
return item
이 방법 은 실질 적 으로
item
기본 파일 이름 을 저장 한 후 파일 이름 을 바 꾸 는 것 이다.3.ImagePipline 소스 코드 에 대한 분석
원본 코드 를 읽 으 면
ImagesPipline
방법 이 바로 그림 에 파일 이름 을 부여 하 는 방법 임 을 알 수 있다.그 러 니까 이 방법 을 직접 다시 쓰 는 게 좋 지 않 겠 습 니까?여기 서 우 리 는 먼저file_path()
방법의 소스 코드 를 살 펴 보 자.def file_path(self, request, response=None, info=None):
## start of deprecation warning block (can be removed in the future)
def _warn():
from scrapy.exceptions import ScrapyDeprecationWarning
import warnings
warnings.warn('ImagesPipeline.image_key(url) and file_key(url) methods are deprecated, '
'please use file_path(request, response=None, info=None) instead',
category=ScrapyDeprecationWarning, stacklevel=1)
# check if called from image_key or file_key with url as first argument
if not isinstance(request, Request):
_warn()
url = request
else:
url = request.url
# detect if file_key() or image_key() methods have been overridden
if not hasattr(self.file_key, '_base'):
_warn()
return self.file_key(url)
elif not hasattr(self.image_key, '_base'):
_warn()
return self.image_key(url)
## end of deprecation warning block
image_guid = hashlib.sha1(url).hexdigest() # change to request.url after deprecation
return 'full/%s.jpg' % (image_guid)
파일 경 로 를 수정 하기 위해 수정
file_path()
한 것 이 라면 원본 코드 에 대한 침입 이 너무 크다.그래서 공식 문서 에 도 재 작성 을 건의 하지 않 았 다file_path
.다음은 Images Pinpline 의 소스 코드 입 니 다.참고 하 시기 바 랍 니 다.
class ImagesPipeline(FilesPipeline):
"""Abstract pipeline that implement the image thumbnail generation logic
"""
MEDIA_NAME = 'image'
MIN_WIDTH = 0
MIN_HEIGHT = 0
THUMBS = {}
DEFAULT_IMAGES_URLS_FIELD = 'image_urls'
DEFAULT_IMAGES_RESULT_FIELD = 'images'
@classmethod
def from_settings(cls, settings):
cls.MIN_WIDTH = settings.getint('IMAGES_MIN_WIDTH', 0)
cls.MIN_HEIGHT = settings.getint('IMAGES_MIN_HEIGHT', 0)
cls.EXPIRES = settings.getint('IMAGES_EXPIRES', 90)
cls.THUMBS = settings.get('IMAGES_THUMBS', {})
s3store = cls.STORE_SCHEMES['s3']
s3store.AWS_ACCESS_KEY_ID = settings['AWS_ACCESS_KEY_ID']
s3store.AWS_SECRET_ACCESS_KEY = settings['AWS_SECRET_ACCESS_KEY']
cls.IMAGES_URLS_FIELD = settings.get('IMAGES_URLS_FIELD', cls.DEFAULT_IMAGES_URLS_FIELD)
cls.IMAGES_RESULT_FIELD = settings.get('IMAGES_RESULT_FIELD', cls.DEFAULT_IMAGES_RESULT_FIELD)
store_uri = settings['IMAGES_STORE']
return cls(store_uri)
def file_downloaded(self, response, request, info):
return self.image_downloaded(response, request, info)
def image_downloaded(self, response, request, info):
checksum = None
for path, image, buf in self.get_images(response, request, info):
if checksum is None:
buf.seek(0)
checksum = md5sum(buf)
width, height = image.size
self.store.persist_file(
path, buf, info,
meta={'width': width, 'height': height},
headers={'Content-Type': 'image/jpeg'})
return checksum
def get_images(self, response, request, info):
path = self.file_path(request, response=response, info=info)
orig_image = Image.open(StringIO(response.body))
width, height = orig_image.size
if width < self.MIN_WIDTH or height < self.MIN_HEIGHT:
raise ImageException("Image too small (%dx%d < %dx%d)" %
(width, height, self.MIN_WIDTH, self.MIN_HEIGHT))
image, buf = self.convert_image(orig_image)
yield path, image, buf
for thumb_id, size in self.THUMBS.iteritems():
thumb_path = self.thumb_path(request, thumb_id, response=response, info=info)
thumb_image, thumb_buf = self.convert_image(image, size)
yield thumb_path, thumb_image, thumb_buf
def convert_image(self, image, size=None):
if image.format == 'PNG' and image.mode == 'RGBA':
background = Image.new('RGBA', image.size, (255, 255, 255))
background.paste(image, image)
image = background.convert('RGB')
elif image.mode != 'RGB':
image = image.convert('RGB')
if size:
image = image.copy()
image.thumbnail(size, Image.ANTIALIAS)
buf = StringIO()
image.save(buf, 'JPEG')
return image, buf
def get_media_requests(self, item, info):
return [Request(x) for x in item.get(self.IMAGES_URLS_FIELD, [])]
def item_completed(self, results, item, info):
if self.IMAGES_RESULT_FIELD in item.fields:
item[self.IMAGES_RESULT_FIELD] = [x for ok, x in results if ok]
return item
def file_path(self, request, response=None, info=None):
## start of deprecation warning block (can be removed in the future)
def _warn():
from scrapy.exceptions import ScrapyDeprecationWarning
import warnings
warnings.warn('ImagesPipeline.image_key(url) and file_key(url) methods are deprecated, '
'please use file_path(request, response=None, info=None) instead',
category=ScrapyDeprecationWarning, stacklevel=1)
# check if called from image_key or file_key with url as first argument
if not isinstance(request, Request):
_warn()
url = request
else:
url = request.url
# detect if file_key() or image_key() methods have been overridden
if not hasattr(self.file_key, '_base'):
_warn()
return self.file_key(url)
elif not hasattr(self.image_key, '_base'):
_warn()
return self.image_key(url)
## end of deprecation warning block
image_guid = hashlib.sha1(url).hexdigest() # change to request.url after deprecation
return 'full/%s.jpg' % (image_guid)
def thumb_path(self, request, thumb_id, response=None, info=None):
## start of deprecation warning block (can be removed in the future)
def _warn():
from scrapy.exceptions import ScrapyDeprecationWarning
import warnings
warnings.warn('ImagesPipeline.thumb_key(url) method is deprecated, please use '
'thumb_path(request, thumb_id, response=None, info=None) instead',
category=ScrapyDeprecationWarning, stacklevel=1)
# check if called from thumb_key with url as first argument
if not isinstance(request, Request):
_warn()
url = request
else:
url = request.url
# detect if thumb_key() method has been overridden
if not hasattr(self.thumb_key, '_base'):
_warn()
return self.thumb_key(url, thumb_id)
## end of deprecation warning block
thumb_guid = hashlib.sha1(url).hexdigest() # change to request.url after deprecation
return 'thumbs/%s/%s.jpg' % (thumb_id, thumb_guid)
# deprecated
def file_key(self, url):
return self.image_key(url)
file_key._base = True
# deprecated
def image_key(self, url):
return self.file_path(url)
image_key._base = True
# deprecated
def thumb_key(self, url, thumb_id):
return self.thumb_path(url, thumb_id)
thumb_key._base = True
소결
『8195』scrapy 자체 가 제공 하 는 도 구 는 이미 풍부 하고 실 용적 입 니 다.저 는 scrapy 에 대한 이해 에 한계 가 있 습 니 다.입문 일 뿐 입 니 다.본 블 로그 도 제 가
file_path
독학 후의 총 결 일 뿐 입 니 다.잘못 이 있 으 면 지적 해 주 십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.