অনুরোধগুলি ব্যবহার করে কীভাবে চিত্র ডাউনলোড করবেন


367

আমি পাইথনের requestsমডিউলটি ব্যবহার করে ওয়েব থেকে একটি চিত্র ডাউনলোড এবং সংরক্ষণ করার চেষ্টা করছি ।

আমি ব্যবহৃত (কার্যকারী) কোডটি এখানে:

img = urllib2.urlopen(settings.STATICMAP_URL.format(**data))
with open(path, 'w') as f:
    f.write(img.read())

এখানে নতুন (অ-কর্মক্ষম) কোডটি ব্যবহার করছে requests:

r = requests.get(settings.STATICMAP_URL.format(**data))
if r.status_code == 200:
    img = r.raw.read()
    with open(path, 'w') as f:
        f.write(img)

আপনি যে প্রতিক্রিয়াটি থেকে ব্যবহার করতে পারেন তাতে কোন বৈশিষ্ট্য সম্পর্কে আমাকে সাহায্য করতে পারেন requests?


15
r.raw ব্যবহার করতে আপনার প্রবাহ সেট করতে হবে = সত্য
ক্লাসং

উত্তর:


516

আপনি হয় response.rawফাইল অবজেক্টটি ব্যবহার করতে পারেন , বা প্রতিক্রিয়ার মাধ্যমে পুনরাবৃত্তি করতে পারেন ।

response.rawফাইল-জাতীয় অবজেক্টটি ব্যবহার করতে, ডিফল্টরূপে সংকোচিত প্রতিক্রিয়াগুলি ডিকোড করে না (GZIP বা ডিফল্ট সহ)। আপনি এটির জন্য decode_contentঅ্যাট্রিবিউট সেট করে যাইহোক আপনার জন্য ডিকম্প্রেস করতে বাধ্য করতে পারেন True( requestsএটি Falseডিকোডিং নিজেই নিয়ন্ত্রণ করতে সেট করে)। তারপরে আপনি shutil.copyfileobj()পাইথন কোনও ফাইল অবজেক্টে ডেটা স্ট্রিম করতে ব্যবহার করতে পারেন:

import requests
import shutil

r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
    with open(path, 'wb') as f:
        r.raw.decode_content = True
        shutil.copyfileobj(r.raw, f)        

প্রতিক্রিয়াটি পুনরাবৃত্তি করতে একটি লুপ ব্যবহার করুন; এরূপ পুনরাবৃত্তি নিশ্চিত করে যে ডেটা এই পর্যায়ে সংক্ষেপিত হয়:

r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
    with open(path, 'wb') as f:
        for chunk in r:
            f.write(chunk)

এটি 128 বাইট খণ্ডে ডেটা পড়বে; আপনি যদি মনে করেন অন্য খণ্ডের আকার আরও ভাল কাজ করে তবে একটি কাস্টম খণ্ড আকারের Response.iter_content()পদ্ধতিটি ব্যবহার করুন :

r = requests.get(settings.STATICMAP_URL.format(**data), stream=True)
if r.status_code == 200:
    with open(path, 'wb') as f:
        for chunk in r.iter_content(1024):
            f.write(chunk)

নোট করুন যে পাইথন আপনার জন্য নতুন লাইনের চেষ্টা ও অনুবাদ না করে তা নিশ্চিত করার জন্য আপনাকে গন্তব্য ফাইলটি বাইনারি মোডে খুলতে হবে open আমরা সেটও করেছি stream=Trueযাতে requestsপুরো চিত্রটি মেমরিতে প্রথমে ডাউনলোড না হয়।


2
আমি টেক্সট ফাইল ডাটা খুঁজে পেতে সক্ষম, আমি ব্যবহার পদক্ষেপ পারে আপনার উত্তর সাহায্যে হয় r2 = requests.post(r.url, data); print r2.content। তবে এখন আমিও জানতে চাই filename। তাদের কোন পরিষ্কার উপায়? - বর্তমানে আমি শিরোনামে ফাইলের নাম খুঁজে পেয়েছি - r2.headers['content-disposition'] যা আমাকে এইভাবে আউটপুট দেয়: 'attachment; filename=DELS36532G290115.csi' আমি ফাইলের জন্য এই স্ট্রিংটি পার্স করছি ... তাদের কোনও ক্লিনার উপায় কি?
গ্রিজেশ চৌহান

6
@ গ্রিজেশচৌহান: হ্যাঁ, শিরোনামটি content-dispositionএখানে যাওয়ার উপায়; cgi.parse_header()এটি পার্স করতে এবং পরামিতিগুলি পেতে ব্যবহার করুন ; params = cgi.parse_header(r2.headers['content-disposition'])[1]তারপর params['filename']
মার্তিজান পিটারস

1
ডিফল্ট 128 বাইট খন্ডে পেতে, আপনি প্রয়োজন পুনরুক্তি requests.Responseনিজেই : for chunk in r: ...। উইল iter_content()ছাড়াই কল করা 1 বাইট খণ্ডে পুনরাবৃত্তিchunk_size হবে ।
dtk

@ ডিটিকে: ধন্যবাদ, আমি উত্তরটি আপডেট করব। আমি আমার উত্তর পোস্ট করার পরে Iteration পরিবর্তন করা হয়েছে
মার্টিজন পিটারস

1
@ কুমজ দু'টি কারণ: response.okকখনই নথিভুক্ত করা হয়নি এবং এটি যে কোনও 1XX, 2XX বা 3xx স্থিতির জন্য সত্য তা উত্পাদন করে তবে কেবল ২০০ টির প্রতিক্রিয়াটির প্রতিক্রিয়া রয়েছে body
মার্টিজান পিটারস

232

অনুরোধ থেকে একটি ফাইল-জাতীয় বস্তু পান এবং এটি একটি ফাইলে অনুলিপি করুন। এটি একবারে স্মৃতিতে পুরো জিনিসটি পড়া এড়াবে।

import shutil

import requests

url = 'http://example.com/img.png'
response = requests.get(url, stream=True)
with open('img.png', 'wb') as out_file:
    shutil.copyfileobj(response.raw, out_file)
del response

14
ফিরে এসে উত্তর দেওয়ার জন্য আপনাকে অনেক ধন্যবাদ। যদিও অন্য উত্তরটি কাজ করে তবে এইটি একটি লাফিয়ে ও সহজ সরল
dkroy

11
এটি লক্ষণীয় যে কয়েকটি সার্ভার তাদের চিত্রগুলি GZIP এ সেট করেছে কারণ চিত্রগুলি ইতিমধ্যে তাদের নিজস্ব সংকোচনে রয়েছে। এটি প্রতিরক্ষামূলক, সামান্য সুবিধা দিয়ে সিপিইউ চক্র অপচয় করে। সুতরাং এটি পাঠ্য সামগ্রীতে সমস্যা হতে পারে, বিশেষত চিত্রগুলির সাথে এটি নয়।
phette23

3
আসল ফাইল
নামটি

@ phette23 এটিও লক্ষ্য করার মতো যে গুগল পেজস্পিড প্রতিবেদন করে এবং এটি ডিফল্টরূপে করে।
ওয়ার্নাইট

8
সেট করা উচিত r.raw.decode_content = Trueআগে shutil.copyfileobj(response.raw, out_file)কারণ by default, decode compressed responses (with GZIP or deflate), তাই আপনি একটি শূন্য-ফাইল চিত্র পাবেন।
সিমিন জি

166

এটি সম্পর্কে কীভাবে, একটি দ্রুত সমাধান।

import requests

url = "http://craphound.com/images/1006884_2adf8fc7.jpg"
response = requests.get(url)
if response.status_code == 200:
    with open("/Users/apple/Desktop/sample.jpg", 'wb') as f:
        f.write(response.content)

1
আপনি কি বলতে চাইছেন! f = open("/Users/apple/Desktop/sample.jpg", 'wb')এই পথ দিয়ে কী বোঝাতে চাইছেন !? আমি চিত্রটি ডাউনলোড করতে চাই
হাসি

3
এটি নির্দিষ্ট করা পথে একটি ফাইল বর্ণনাকারী খুলবে যা ইমেজ ফাইলটি লেখা যেতে পারে।
কিরণবকৃষ্ণ

@ অ্যান্ড্রুগ্লাজকভ আমি মনে করি এটি ব্যবহার করা আরও বেশি পাইথোনিক হবেif response.ok:
এন্ডারম্যানাপএম

5
প্রতিক্রিয়া.োক যে কোনও 1XX, 2XX বা 3xx স্থিতির জন্য সত্য, তবে উপরের মন্তব্যে উল্লিখিত @ মার্তিজান পিটার হিসাবে কেবল একটি 200 টি প্রতিক্রিয়া রয়েছে
এন্টারেন্ড্রে

75

অনুরোধগুলি ব্যবহার করে চিত্রগুলি ডাউনলোড করার জন্য আমার একই প্রয়োজন। আমি প্রথমে মার্তিজান পিটারের উত্তরটি চেষ্টা করেছি এবং এটি ভালভাবে কাজ করে। তবে যখন আমি এই সাধারণ ফাংশনটিতে একটি প্রোফাইল করেছি, আমি দেখতে পেয়েছি যে এটি urllib এবং urllib2 এর তুলনায় অনেকগুলি ফাংশন কল ব্যবহার করে।

আমি তখন অনুরোধ মডিউলটির লেখক দ্বারা প্রস্তাবিত উপায়টি চেষ্টা করেছি :

import requests
from PIL import Image
# python2.x, use this instead  
# from StringIO import StringIO
# for python3.x,
from io import StringIO

r = requests.get('https://example.com/image.jpg')
i = Image.open(StringIO(r.content))

এটি আরও অনেক বেশি ফাংশন কলগুলির সংখ্যা হ্রাস করেছে, এইভাবে আমার অ্যাপ্লিকেশনটিকে ত্বরান্বিত করে। এখানে আমার প্রোফাইলারের কোড এবং ফলাফল।

#!/usr/bin/python
import requests
from StringIO import StringIO
from PIL import Image
import profile

def testRequest():
    image_name = 'test1.jpg'
    url = 'http://example.com/image.jpg'

    r = requests.get(url, stream=True)
    with open(image_name, 'wb') as f:
        for chunk in r.iter_content():
            f.write(chunk)

def testRequest2():
    image_name = 'test2.jpg'
    url = 'http://example.com/image.jpg'

    r = requests.get(url)

    i = Image.open(StringIO(r.content))
    i.save(image_name)

if __name__ == '__main__':
    profile.run('testUrllib()')
    profile.run('testUrllib2()')
    profile.run('testRequest()')

পরীক্ষার ফলাফলের জন্য ফলাফল:

343080 function calls (343068 primitive calls) in 2.580 seconds

এবং পরীক্ষার ফলাফলের জন্য ফলাফল 2:

3129 function calls (3105 primitive calls) in 0.024 seconds

12
এটি কারণ যে আপনি chunk_sizeপ্যারামিটারটি 1 এর ডিফল্ট নির্দিষ্ট করে নেই , তাই iter_contentএকসময় ফলাফল স্ট্রিম 1 বাইট দ্বারা পুনরাবৃত্তি হয়। পাইথন-রিকোয়েস্টস.আর.ইন / স্লেস্ট / এপি // ডকুমেন্টেশন দেখুন ।
ক্যাডেন্ট অরেঞ্জ

9
এটি পুরো প্রতিক্রিয়াটিকে মেমরিতে লোড করে, যা আপনি এড়াতে চাইতে পারেন। এখানে কোনও ব্যবহার করার দরকার নেই PIL, কেবল with open(image_name, 'wb') as outfile: outfile.write(r.content)যথেষ্ট।
মার্টিজন পিটারস

3
PILএটিকে স্ট্যান্ডার্ড লাইব্রেরিতেও কিছুটা কম পোর্টেবল বানানো নয়।
jjj

2
@ ঝেনিইজ্যাং iter_contentধীর কারণ আপনার chunk_sizeখুব ছোট, আপনি এটি 100 কে বাড়িয়ে দিলে এটি আরও দ্রুত হবে।
ওয়াং

এটি সেরা উত্তর। মেমরির মধ্যে ফাইলটি পড়া সর্বদা সেরা নয়, তবে ওপি "ইমেজ" নির্দিষ্ট করেছে যার অর্থ ফাইলগুলি সাধারণত 4MB এর চেয়ে কম হবে, এইভাবে মেমরির উপর তুচ্ছ প্রভাব ফেলবে।
ক্রিস কনলান

51

এটি ব্যবহারের চেয়ে সহজ হতে পারে requests। আমি কেবল কখনও requestsএইচটিটিপি স্টাফ ব্যবহার না করার পরামর্শ দেব suggest

দুটি লাইনার ব্যবহার করে urllib:

>>> import urllib
>>> urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

একটি দুর্দান্ত পাইথন মডিউলও রয়েছে wgetযা ব্যবহার করা বেশ সহজ। এখানে পাওয়া গেছে

এটি নকশার সরলতা প্রদর্শন করে:

>>> import wget
>>> url = 'http://www.futurecrew.com/skaven/song_files/mp3/razorback.mp3'
>>> filename = wget.download(url)
100% [................................................] 3841532 / 3841532>
>> filename
'razorback.mp3'

উপভোগ করুন।

সম্পাদনা করুন: আপনি outকোনও পাথ নির্দিষ্ট করতে একটি পরামিতি যুক্ত করতে পারেন ।

>>> out_filepath = <output_filepath>    
>>> filename = wget.download(url, out=out_filepath)

আমি wgetকোন ঝামেলা ছাড়াই ব্যবহার করেছি । ব্যবহারের সুবিধা জানায় জন্য ধন্যবাদurllib3
h3xh4wk

1
দ্রষ্টব্য যে এই উত্তরটি পাইথন ২ এর জন্য Py পাইথন 3 এর জন্য আপনাকে যা করতে হবে urllib.request.urlretrieve("http://example.com", "file.ext")
হুস্কি

1
ধন্যবাদ @ হাস্কি আপডেট করা হয়েছে।
ব্লেয়ারজ 23

28

নিম্নলিখিত কোড স্নিপেট একটি ফাইল ডাউনলোড করে।

নির্দিষ্ট ইউআরএল হিসাবে ফাইলটি তার ফাইল নাম দিয়ে সংরক্ষণ করা হয়।

import requests

url = "http://example.com/image.jpg"
filename = url.split("/")[-1]
r = requests.get(url, timeout=0.5)

if r.status_code == 200:
    with open(filename, 'wb') as f:
        f.write(r.content)

16

দুটি প্রধান উপায় আছে:

  1. .content(সর্বাধিক সরল / সরকারী) ব্যবহার ( ঝেনি জ্যাংয়ের উত্তর দেখুন ):

    import io  # Note: io.BytesIO is StringIO.StringIO on Python2.
    import requests
    
    r = requests.get('http://lorempixel.com/400/200')
    r.raise_for_status()
    with io.BytesIO(r.content) as f:
        with Image.open(f) as img:
            img.show()
  2. ব্যবহার করে .raw( মার্টিজান পিটারের উত্তর দেখুন ):

    import requests
    
    r = requests.get('http://lorempixel.com/400/200', stream=True)
    r.raise_for_status()
    r.raw.decode_content = True  # Required to decompress gzip/deflate compressed responses.
    with PIL.Image.open(r.raw) as img:
        img.show()
    r.close()  # Safety when stream=True ensure the connection is released.

উভয় সময় নির্ধারিত পার্থক্য দেখায় না।


2
আমি একগুচ্ছ উত্তর চেষ্টা করেছি, এবং আপনার 1.উত্তর (ব্যবহার io.BytesIOএবং Image) প্রথমটি পাইথন ৩.6 এ আমার জন্য কাজ করেছিল। from PIL import Image(এবং pip install Pillow) ভুলবেন না ।
কল্লিন

। কনটেন্ট এবং .আরও এর মধ্যে আলাদা কী?
ফক্সিরিস

13

ইমেজ এবং অনুরোধ আমদানি করা হিসাবে সহজ

from PIL import Image
import requests

img = Image.open(requests.get(url, stream = True).raw)
img.save('img1.jpg')

4

এখানে আরও ব্যবহারকারী-বান্ধব উত্তর যা এখনও স্ট্রিমিং ব্যবহার করে।

শুধু এই ফাংশন সংজ্ঞা এবং কল getImage()। এটি ইউআরএল হিসাবে একই ফাইলের নাম ব্যবহার করবে এবং বর্তমান ডিরেক্টরিতে ডিফল্টরূপে লিখবে, তবে উভয়ই পরিবর্তন করা যেতে পারে।

import requests
from StringIO import StringIO
from PIL import Image

def createFilename(url, name, folder):
    dotSplit = url.split('.')
    if name == None:
        # use the same as the url
        slashSplit = dotSplit[-2].split('/')
        name = slashSplit[-1]
    ext = dotSplit[-1]
    file = '{}{}.{}'.format(folder, name, ext)
    return file

def getImage(url, name=None, folder='./'):
    file = createFilename(url, name, folder)
    with open(file, 'wb') as f:
        r = requests.get(url, stream=True)
        for block in r.iter_content(1024):
            if not block:
                break
            f.write(block)

def getImageFast(url, name=None, folder='./'):
    file = createFilename(url, name, folder)
    r = requests.get(url)
    i = Image.open(StringIO(r.content))
    i.save(file)

if __name__ == '__main__':
    # Uses Less Memory
    getImage('http://www.example.com/image.jpg')
    # Faster
    getImageFast('http://www.example.com/image.jpg')

requestএর সাহস getImage()উত্তর এর উপর ভিত্তি করে এখানে এবং সাহস getImageFast()উত্তর এর উপর ভিত্তি করে উপরে


3

আমি একটি মন্তব্য পোস্ট করতে যাচ্ছি কারণ আমার কাছে মন্তব্য করার মতো পর্যাপ্ত প্রতিনিধি নেই, তবে ব্লেয়ারগ 23 দ্বারা পোস্ট করা উইজেটের সাহায্যে আপনিও পথটির জন্য একটি আউট প্যারামিটার সরবরাহ করতে পারেন।

 wget.download(url, out=path)

2

অনুরোধের সাথে বাইনারি ফাইল কীভাবে ডাউনলোড করতে হয় তা গুগল অনুসন্ধানের জন্য এটিই প্রথম প্রতিক্রিয়া। আপনার যদি অনুরোধগুলির সাথে একটি স্বেচ্ছাসেবী ফাইল ডাউনলোড করতে হয় তবে আপনি এটি ব্যবহার করতে পারেন:

import requests
url = 'https://s3.amazonaws.com/lab-data-collections/GoogleNews-vectors-negative300.bin.gz'
open('GoogleNews-vectors-negative300.bin.gz', 'wb').write(requests.get(url, allow_redirects=True).content)

1
নিস! এটি এমনকি একটি অন্তর্নিহিত আছে .close()। আমার ধারণা, এটি ২০১২ সালের সেরা উত্তর।
ড্যানিয়েল ডাব্লু।

2

এইভাবে আমি এটি করেছি

import requests
from PIL import Image
from io import BytesIO

url = 'your_url'
files = {'file': ("C:/Users/shadow/Downloads/black.jpeg", open('C:/Users/shadow/Downloads/black.jpeg', 'rb'),'image/jpg')}
response = requests.post(url, files=files)

img = Image.open(BytesIO(response.content))
img.show()

-1

আপনি এর মতো কিছু করতে পারেন:

import requests
import random

url = "https://images.pexels.com/photos/1308881/pexels-photo-1308881.jpeg? auto=compress&cs=tinysrgb&dpr=1&w=500"
name=random.randrange(1,1000)
filename=str(name)+".jpg"
response = requests.get(url)
if response.status_code.ok:
   with open(filename,'w') as f:
    f.write(response.content)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.