有人說, 不爬妹子的爬蟲不是一隻好爬蟲, 怎麼海量爬取網路上的圖片, 有時還蠻重要的. 只是蠻浪費硬碟空間就是了.
安裝套件
PIL套件的使用, 需使用如下指令安裝
pip install pillow
os.path.basename
完整url如 http://www.win4000.com/1234.jpg, 可利用os.path.basename取得1234.jpg檔名, 當成儲存在本地端硬碟的檔案名稱
Image.open
取得網路照片的網址時, 可利用Image.open(BytesIO(requests.get(url).content) 將照片取回存放在image物件
最後再由image.save(filename) 儲存在硬碟中
requests text 與content的差異
page=requests(url), 經由requests取得物件page,可以使用 page.text 返回 Unicode 格式,也就是文字模式。但如果 page 裏的內容是圖片等二進位碼,則需使用 page.content 返回二進位數據。
簡易下載圖片
底下使用 requests取得圖片的資料page,再使用BytesIO將 page.content轉成Image格式,然後就可以將Image save到檔案,或plt顯圖出來
請先安裝如下套件
pip install requests matplotlib Pillow
import os from io import BytesIO import requests from PIL import Image import pylab as plt url='/wp-content/uploads/2016/10/img_6279.jpg' page = requests.get(url) file=os.path.basename(url) print(file) image = Image.open(BytesIO(page.content)) image.save(f"d:/{file}") plt.imshow(image) plt.show()
Projector專案
底下代碼,利用 requests 及 PyQt5 作出一個投影片
G.py
delay=10
width=0
height=0
ls=["http://mahaljsp.asuscomm.com/lcc/pictures/976519.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/976520.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/976521.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/993512.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/993513.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/993514.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/993515.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_172815.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_172828.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_172831.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_172833.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_172837.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_172855.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_172857.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_172957.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_173001.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_173004.jpg",
"http://mahaljsp.asuscomm.com/lcc/pictures/IMG_20211003_173015.jpg"]
Projector.py
import G, os, sys, cv2
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog
from GetImage import GetPictureThread
from ui.ui_mainwindow import Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.slider.valueChanged.connect(self.changeTime)
self.thread=GetPictureThread()
self.thread.callback.connect(self.draw)
self.thread.start()
def resizeEvent(self, event):
G.width = self.lblPicture.width()
G.height = self.lblPicture.height()
#self.lblPicture.setScaledContents(True)
def changeTime(self):
G.delay=self.slider.value()
def draw(self, image):
sWidth=G.width
sHeight=G.height
pWidth=image.shape[1]
pHeight=image.shape[0]
pRate=pWidth/pHeight
sRate=sWidth/sHeight
if sRate>pRate:
height=sHeight
width = height*pRate
else:
width=sWidth
height=width/pRate
img = cv2.resize(image, (int(width), int(height)), interpolation=cv2.INTER_LINEAR)
img = QImage(img, img.shape[1], img.shape[0], img.shape[1] * 3, QImage.Format_RGB888)
pix = QPixmap(img)
self.lblPicture.setPixmap(pix)
if __name__=='__main__':
app=QApplication(sys.argv)
mainwindow=MainWindow()
mainwindow.showMaximized()
app.exec()
GetImage.py
from io import BytesIO
import numpy as np
from PIL import Image
from PyQt5.QtCore import QThread, pyqtSignal
import G
import requests
class GetPictureThread(QThread):
callback=pyqtSignal(np.ndarray)
def __init__(self, parent=None):
super().__init__(parent)
self.runFlag=True
def run(self):
images=[]
for url in G.ls:
page = requests.get(url)
image = Image.open(BytesIO(page.content))
images.append(image)
self.callback.emit(np.array(image))
index=0
qty=len(images)
while self.runFlag:
image=images[index]
self.callback.emit(np.array(image))
index=(index+1)%qty
self.msleep(G.delay)
ui_mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>763</width>
<height>561</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lblPicture">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>播放速度</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slider">
<property name="minimumSize">
<size>
<width>500</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>3000</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>100</number>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblPath">
<property name="minimumSize">
<size>
<width>400</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>50</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnPath">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>瀏覽</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>763</width>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menu">
<property name="title">
<string>檔案</string>
</property>
<addaction name="actionOpen"/>
<addaction name="actionOpen_old"/>
</widget>
<widget class="QMenu" name="menu_2">
<property name="title">
<string>編輯</string>
</property>
</widget>
<addaction name="menu"/>
<addaction name="menu_2"/>
</widget>
<action name="actionOpen">
<property name="text">
<string>Open New</string>
</property>
</action>
<action name="actionOpen_old">
<property name="text">
<string>Open old</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
上傳圖片
假設我們的網站允許上傳圖片,模板表單 photo_form.html 內容如下
{% extends 'base.html' %}
{% block content1 %}
<form action="/photo_save/" method="post" enctype="multipart/form-data">
<table border="1" cellpadding="0" cellspacing="0">
<tr align="center">
<td>
上傳圖片
</td>
</tr>
<tr align="center">
<td>
<input type="file" name="userFile">
</td>
</tr>
<tr align="center">
<td>
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>
{% endblock %}
而 python 的 upload.py 內容如下
import os
from django.http import HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
def html(request):
return render(
request,
"photo_form.html"
)
@csrf_exempt
def save_file(request):
if request.method=="POST":
file=request.FILES.get("userFile")
if file is not None:
path=os.path.join("e:/server/upload", str(file))
with open(path, 'wb')as f:
for data in file.chunks():
f.write(data)
return render(
request,
"photo_form.html"
)
else:
return HttpResponse("error")
此時我們可以使用 requests 將圖片傳給 save_file 函數,完整代碼如下。
import requests url = "https://mahalrtc.ddns.net/photo_save/" files = { "userFile": ("dog.jpg", open("dog.jpg", "rb"), "image/jpeg") } response = requests.post(url, files=files) print("狀態碼:", response.status_code)