webdevqa.jp.net

PILでインターネットから画像を開くにはどうすればよいですか?

インターネットで画像の大きさを知りたい。使ってみた

_from PIL import Image
import urllib2 as urllib
fd = urllib.urlopen("http://a/b/c")
im = Image.open(fd)
im.size
_

この答え で提案されているように、エラーメッセージが表示されます

_addinfourl instance has no attribute 'seek'
_

私がチェックしたところ、urllib2.urlopen(url)によって返されたオブジェクトには、dirによるシークメソッドがないようです。

では、インターネットからPILにイメージをロードできるようにするにはどうすればよいですか?

25
murgatroid99

io.BytesIO前方互換性 の場合。
StringIOモジュールとcStringIOモジュールはPython 3。

from PIL import Image
import urllib2 as urllib
import io

fd = urllib.urlopen("http://a/b/c")
image_file = io.BytesIO(fd.read())
im = Image.open(image_file)
36

同じ例を使用して、StringIOを使用してバッファを適切なファイルのようなオブジェクトにラップします。

from PIL import Image
import urllib2 as urllib
from StringIO import StringIO

fd = urllib.urlopen("http://a/b/c")
im = Image.open(StringIO(fd.read()))
im.size
8
jdi

Python requestsを使用:

from PIL import Image
from StringIO import StringIO
import requests

r = requests.get("http://a/b/c")
im = Image.open(StringIO(r.content))
im.size
8
Matt Parrilla

この pull-request は、Pillow(フレンドリーなPILフォーク)にネイティブのストリーム処理のサポートを追加し、バージョン2.8.0以降で利用可能になるはずです。これにより、リモートファイルを rllib で簡単に開くことができます。

from PIL import Image
import urllib2
Image.open(urllib2.urlopen(url))

...または requests を使用:

from PIL import Image
import requests
Image.open(requests.get(url, stream=True).raw)

として PRのmjpietersによって述べられています 要求はgzip応答を自動的にデコードしません。そのため、何らかの理由でさらに圧縮された画像をダウンロードする場合は、decode_content=Trueを設定する必要があります.rawにアクセスする前の応答オブジェクト。

response = requests.get(url, stream=True)
response.raw.decode_content = True
image = Image.open(response.raw)
6
mfitzp

urllib documentation は、urlopenによって返されるオブジェクトがseek操作をサポートしていないことを述べています。

このモジュールは、World Wide Web全体でデータをフェッチするための高レベルのインターフェースを提供します。特に、urlopen()関数は組み込み関数open()に似ていますが、ファイル名の代わりにユニバーサルリソースロケーター(URL)を受け入れます。いくつかの制限が適用されます—読み取り用のURLのみを開くことができ、シーク操作は使用できません。

しかし - PIL.open 関数は明示的にそれを必要とします。

open

Image.open(infile)=>画像

Image.open(infile、mode)=>画像

指定された画像ファイルを開いて識別します。これは遅延操作です。実際の画像データは、データを処理しようとするまで読み込まれません(loadメソッドを呼び出して強制的に読み込みます)。 mode引数を指定する場合は、「r」にする必要があります。

文字列(ファイル名を表す)またはファイルオブジェクトを使用できます。後者の場合、ファイルオブジェクトは、read、seek、tellメソッドを実装し、バイナリモードで開く必要があります。

文字列をファイルのようなオブジェクトに変換するcStringIOモジュールを使用してみてください。

from PIL import Image
import urllib2 as urllib
import cStringIO

fd = urllib.urlopen("http://a/b/c")
image_file = cStringIO.StringIO(fd.read())
im = Image.open(image_file)
im.size
2