ไม่สามารถดาวน์โหลดภาพจากลิงก์ url โดยใช้ Python

ฉันต้องการดาวน์โหลดรูปภาพจากเว็บ แต่กลับได้รับข้อผิดพลาดเสมอไม่ว่าจะใช้วิธีใดก็ตาม อย่างไรก็ตาม ฉันไม่มีปัญหาในการดาวน์โหลดภาพอื่นโดยใช้วิธีนี้

ใช้งานได้ - https://mobec.sk/proxy/geo?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng8&TRANSPARENT=true&layers=global%3Abase&tiled=true&STYLES=&WIDTH=512&HEIGHT=512&CRS=EPSG%3A3857&FORMAT_OPTIONS=dpi%3A180&BBOX=1934774.0599543825%2C6239707.492975509%2C1937220.044859508%2C6242153.477880634

ใช้งานไม่ได้ - https://mobec.sk/proxy/geo?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&layers=custom%3Avrbovce_elektrina&tiled=true&STYLES=&WIDTH=512&HEIGHT=512&CRS=EPSG%3A3857&FORMAT_OPTIONS=dpi%3A180&BBOX=1947003.9844800085%2C6242153.477880634%2C1949449.969385134%2C6244599.46278576

วิธีที่ 1

การใช้คำขอของ Python และไลบรารี Pillow ที่นี่ควรดาวน์โหลดรูปภาพโดยตรงจาก url

import requests
from PIL import Image
from io import BytesIO

url = 'https://mobec.sk/proxy/geo?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&layers=custom%3Avrbovce_elektrina&tiled=true&STYLES=&WIDTH=512&HEIGHT=512&CRS=EPSG%3A3857&FORMAT_OPTIONS=dpi%3A180&BBOX=1947003.9844800085%2C6242153.477880634%2C1949449.969385134%2C6244599.46278576'

response = requests.get(url)
img = Image.open(BytesIO(response.content))   # error occurs here
img.save('output.png')

ฉันได้รับข้อผิดพลาดต่อไปนี้:

OSError: cannot identify image file <_io.BytesIO object at 0x04956510>

วิธีที่ 2

การใช้ไลบรารี Selenium ของ Python และ Chromedriver ที่นี่ฉันกำลังพยายามแสดงรูปภาพในเว็บเบราว์เซอร์และพิมพ์หน้าจอทั้งหน้าโดยใช้ไลบรารี Selenium

from selenium import webdriver
from PIL import Image
from io import BytesIO

url = 'https://mobec.sk/proxy/geo?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&layers=custom%3Avrbovce_elektrina&tiled=true&STYLES=&WIDTH=512&HEIGHT=512&CRS=EPSG%3A3857&FORMAT_OPTIONS=dpi%3A180&BBOX=1947003.9844800085%2C6242153.477880634%2C1949449.969385134%2C6244599.46278576'

chrome = webdriver.Chrome('path/to/chromedriver')
chrome.get(url)

png = chrome.get_screenshot_as_png()
im = Image.open(BytesIO(png))
im.save('output.png')

chrome.quit()

ปัญหาของวิธีนี้คือรูปภาพไม่ได้โหลด (แสดง) ในเบราว์เซอร์ Chrome ที่เปิดโดยไดรเวอร์ Chromedriver เมื่อวางลิงก์ลงใน Chrome ปกติ (แอปเดสก์ท็อป) ด้วยตนเอง รูปภาพจะปรากฏขึ้น

วิธีที่ 2 - รูปภาพไม่โหลดเข้าสู่ Chrome




คำตอบ (4)


ฉันทดสอบทั้งสองวิธีในลิงก์ทั้งสองและดูเหมือนว่ามีบางอย่างผิดปกติกับลิงก์ที่สอง: วิธีแรกทำงานได้ดีอย่างสมบูรณ์ ไม่ว่าจะเปิดด้วยตนเองด้วยเบราว์เซอร์หรือใช้วิธีใด ๆ เหล่านั้น อันที่สองไม่เปิดในเบราว์เซอร์และให้ข้อผิดพลาดในทั้งสองวิธี (ซึ่งเป็นทั้งโค้ดที่ชาญฉลาด)

ตามที่เขียนไว้ในข้อความแสดงข้อผิดพลาด - Could not find layer custom:vrbovce_elektrina - ทั้งในวิธีการและการวางด้วยตนเอง เบราว์เซอร์ไม่พบเลเยอร์ที่เรียกว่า vrbovce_elektrina อาจมีการพิมพ์ผิดหรือไม่มีรูปภาพ/เลเยอร์ดังกล่าวในหน้านี้

รหัสดีแต่แค่ลิงก์ใช้ไม่ได้

person Piotrek    schedule 17.10.2018
comment
นั่นคือสิ่งที่ฉันคิด. เมื่อฉันคลิกลิงก์ที่สอง เบราว์เซอร์จะพยายามเปิดรูปภาพแต่แจ้งข้อผิดพลาดให้ฉันทราบ (รูปที่ 1) อย่างไรก็ตาม เมื่อฉันคัดลอกลิงก์และวางเป็น URL ลงในแท็บเว็บเบราว์เซอร์ใหม่ รูปภาพก็จะปรากฏขึ้น คุณมีความคิดใด ๆ ว่าทำไมจึงเป็นเช่นนั้น? - person user21816; 17.10.2018
comment
ไม่อยากบอกตรงๆ เพราะฉันไม่สามารถเปิดลิงก์ที่สองได้เลย ลองใช้เบราว์เซอร์ที่แตกต่างกัน ลองใช้ไดรเวอร์ที่แตกต่างกันในซีลีเนียม (chrome, phantomjs ฯลฯ) และฉันยังไม่เห็นภาพ - person Piotrek; 17.10.2018
comment
ฉันคิดว่าปัญหาไม่ได้อยู่ในข้อมูลที่ส่งไปยังเว็บเซิร์ฟเวอร์ในส่วนหัวของคำขอ HTTP (ภาษา, ผู้ใช้, ... ) ฉันได้พยายามที่จะเปลี่ยนส่วนหัวเพื่อที่จะไม่ได้รับข้อมูลที่คำขอถูกส่งโดยสคริปต์หลาม แต่ไม่รู้ว่าทำไมถึงเปิดไม่ได้ (เปิดได้เฉพาะในประเทศผมหรือเปล่า ทำไมเฉพาะชั้นนี้ล่ะ?) - person user21816; 17.10.2018
comment
ใช่ ฉันรู้ว่ามันแปลก จะเป็นประโยชน์เพื่อดูว่ามีใครสามารถเปิดลิงก์ได้หรือไม่ - person Piotrek; 17.10.2018
comment
ในที่สุด ฉันก็สามารถดาวน์โหลดรูปภาพนี้และรูปภาพอื่นๆ ที่คล้ายกันได้แล้ว ฉันไม่รู้ว่าทำไม แต่มันได้ผลเมื่อฉันเปิด URL ต่อไปนี้ก่อน (วิธีที่ 2): mobec.sk/ vrbovce#base (นี่คือเว็บไซต์ที่แสดงแผนที่จากรูปภาพเหล่านี้) - person user21816; 17.10.2018
comment
ดีใจที่มันได้ผล น่าตลกดีที่เปิดแบบที่คุณแนะนำตอนนี้ก็ใช้ได้กับฉันเช่นกัน :) - person Piotrek; 17.10.2018

เนื่องจาก @Piotrek เขียนว่าปัญหาไม่ได้อยู่ในโค้ด ฉันเดาว่าปัญหาอยู่ที่ฝั่งเซิร์ฟเวอร์ นี่คือสิ่งที่ใช้ได้ผลสำหรับฉัน:

  1. ฉันได้ใช้วิธีที่ 2
  2. ก่อนที่จะเปิดลิงก์ URL ฉันได้เปิด URL "พาเรนต์" ต่อไปนี้แล้ว (https://mobec.sk/vrbovce#base) ซึ่งใช้รูปภาพเหล่านี้เพื่อสร้างแผนที่
  3. ในขั้นตอนถัดไป ฉันได้เปิดลิงก์ url ของรูปภาพในเว็บเบราว์เซอร์
    chrome โดยใช้โมดูล selenium python
  4. หลังจากนั้นฉันสามารถจับภาพหน้าจอของภาพได้

นี่คือรหัสที่เหมาะกับฉัน:

from selenium import webdriver
from PIL import Image
from io import BytesIO

web_driver = webdriver.Chrome('path/to/chromedriver')
web_driver.get('https://mobec.sk/vrbovce#base')

web_driver.get('https://mobec.sk/proxy/geo?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&layers=custom%3Avrbovce_elektrina&tiled=true&STYLES=&WIDTH=512&HEIGHT=512&CRS=EPSG%3A3857&FORMAT_OPTIONS=dpi%3A180&BBOX=1947003.9844800085%2C6242153.477880634%2C1949449.969385134%2C6244599.46278576')

png = web_driver.get_screenshot_as_png()
im = Image.open(BytesIO(png))
im.save('output.png')

web_driver.quit()
person user21816    schedule 17.10.2018

ใช้การร้องขอ เพียงแค่เขียนเนื้อหาการตอบกลับไปยังไฟล์:

with open('image-file', 'wb') as fp: 
   fp.write(response.content)
person Vikrant Sharma    schedule 17.10.2018

คุณสามารถใช้ไลบรารี StringIO สำหรับสิ่งนั้นได้

import requests
from PIL import Image
from StringIO import StringIO

url = 'https://mobec.sk/proxy/geo?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng8&TRANSPARENT=true&layers=global%3Abase&tiled=true&STYLES=&WIDTH=512&HEIGHT=512&CRS=EPSG%3A3857&FORMAT_OPTIONS=dpi%3A180&BBOX=1934774.0599543825%2C6239707.492975509%2C1937220.044859508%2C6242153.477880634'

response = requests.request("GET", url)
image = Image.open(StringIO(response.content))
image.save('output.png')

สำหรับ python3;

import requests
from PIL import Image
from io import BytesIO

url = 'https://mobec.sk/proxy/geo?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng8&TRANSPARENT=true&layers=global%3Abase&tiled=true&STYLES=&WIDTH=512&HEIGHT=512&CRS=EPSG%3A3857&FORMAT_OPTIONS=dpi%3A180&BBOX=1934774.0599543825%2C6239707.492975509%2C1937220.044859508%2C6242153.477880634'

response = requests.request("GET", url)
image = Image.open(BytesIO(response.content))
image.save('output.png')
person uedemir    schedule 17.10.2018
comment
from StringIO import StringIO ใช้งานได้ใน Python 2 เท่านั้น ใน Python 3 ใช้ from io import StringIO อย่างไรก็ตาม มันใช้งานไม่ได้เช่นกันและแสดงข้อความแสดงข้อผิดพลาด: TypeError Initial_value ต้องเป็น str หรือ None ไม่ใช่ไบต์ - person user21816; 17.10.2018
comment
ฉันอัปเดตคำตอบสำหรับ python3 และลองใช้โค้ดที่อัปเดตที่ repl.it และทำงานได้ดี - person uedemir; 17.10.2018
comment
ปัญหาคือโค้ดใช้งานไม่ได้กับ url ที่แสดงอยู่ในตัวอย่าง มันทำงานได้ดีกับ URL ที่คุณใช้ตั้งแต่ต้น ลองลิงค์ใช้งานไม่ได้ครับ มันจะไม่ทำงาน โปรดดู 2 ลิงค์แรกในคำถาม ยังไงก็ขอบคุณสำหรับตัวอย่างที่คุณให้มา - person user21816; 17.10.2018