先看知乎上面的一个连接    

 https://www.zhihu.com/question/33646570/answer/157806339

这个哥们通过爬气象网站的气象雷达图,生成一个gif的动态图。非常有趣且很实用,那咱也实现下。

 

我们先实现一个从GIF提取帧的代码

我们这有个gif

 

代码如下:

  1. from PIL import Image
  2. import sys
  3. def processImage(infile):
  4. try:
  5. im = Image.open(infile)
  6. except IOError:
  7. print ("Cant load", infile)
  8. sys.exit(1)
  9. i = 0
  10. mypalette = im.getpalette()
  11. try:
  12. while 1:
  13. im.putpalette(mypalette)
  14. new_im = Image.new("RGBA", im.size)
  15. new_im.paste(im)
  16. new_im.save(\'image\\a\'+str(i)+\'.png\')
  17. i += 1
  18. im.seek(im.tell() + 1)
  19. except EOFError:
  20. pass # end of sequence
  21. processImage(\'source.gif\')

生成效果:

 

从gif提取frame是不是很简单,只需要一个PIL库搞定

但从frame生成gif就麻烦了,因为我们使用的是py3,网上一大堆代码用的是py2.*的 比如 PythonMagick 、 images2gif

还有部分手写gif文件头部GIF89a,调用帧palette、NETSCAPE2.0写入图像等,你们都运行成功了,为什么我没有运行成功呢?

唉!

python就是牛,库如此之多,虽然本人Py一般般,但有前人为你写诗,您只要尾行加句号就可以了。这里我说的是imageio 

下载地址: https://pypi.python.org/pypi/imageio  (Version:2.2.0   by 2017-05-25)

  1. import matplotlib.pyplot as plt
  2. import imageio,os
  3. images = []
  4. filenames=sorted((fn for fn in os.listdir(\'.\') if fn.endswith(\'.png\')))
  5. for filename in filenames:
  6. images.append(imageio.imread(filename))
  7. imageio.mimsave(\'gif.gif\', images,duration=1)

OK! gif生成了!

imageio查看参数: http://imageio.readthedocs.io/

  1. imageio.help(\'gif\')

 

其实,PIL自身也有一个save方法,里面有一个‘save_all’ 参数,意思就是save多个,当format指定为gif时,生成的便是gif的动画

  1. from PIL import Image
  2. im=Image.open("a0.png")
  3. images=[]
  4. images.append(Image.open(\'a1.png\'))
  5. images.append(Image.open(\'a2.png\'))
  6. im.save(\'gif.gif\', save_all=True, append_images=images,loop=1,duration=1,comment=b"aaabb")

读取第一帧,将第一个帧的像素设置为gif像素

 

中国气象网网站: http://products.weather.com.cn/product/radar/index/procode/JC_RADAR_AZ9210_JB      这里是上海南汇雷达站点图

获取数据,我们使用pquery

  1. from pyquery import PyQuery as pq
  2. d = pq(\'http://products.weather.com.cn/product/radar/index/procode/JC_RADAR_AZ9210_JB\')
  3. DomTree = d(\'#slideform #slide option\')

想这个用Image.open 直接打开url的文件路径就可以

  1. images.append(Image.open(\'http://pi.weather.com.cn/i/product/pic/l/sevp_aoc_rdcp_sldas_ebref_az9210_l88_pi_20170621014800000.png\'))

那肯定是失败的:

  1. Traceback (most recent call last):
  2. File "E:/project/test2/my.py", line 29, in <module>
  3. images.append(Image.open(\'http://pi.weather.com.cn/i/product/pic/l/sevp_aoc_rdcp_sldas_ebref_az9210_l88_pi_20170621014800000.png\'))
  4. File "C:\Python36\lib\site-packages\PIL\Image.py", line 2410, in open
  5. fp = builtins.open(filename, "rb")
  6. OSError: [Errno 22] Invalid argument: \'http://pi.weather.com.cn/i/product/pic/l/sevp_aoc_rdcp_sldas_ebref_az9210_l88_pi_20170621014800000.png\'

异想天开呀!!!

imageio支持url文件路径   参考: http://imageio.readthedocs.io/en/latest/examples.html

  1. import imageio
  2. import visvis as vv
  3. im = imageio.imread(\'http://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png\')
  4. vv.imshow(im)

 

使用requests 库保存图片

  1. import requests
  2. r = requests.get(\'http://pi.weather.com.cn/i/product/pic/l/sevp_aoc_rdcp_sldas_ebref_az9210_l88_pi_20170621014800000.png\', timeout=3)
  3. file = open(\'b1.png\', \'wb\')
  4. size = file.write(r.content)
  5. file.close()

 

python 生成gif在上面我们已经说到两种方法,一种是imageio 另一种是PIL自带save_all, 这里我们直接写一个类封装方法

源码如下:

  1. # -*- coding: UTF8 -*-
  2. import requests
  3. from pyquery import PyQuery as pq
  4. import os, sys
  5. import imageio
  6. from PIL import Image
  7. \'\'\'
  8. 天气预报.gif 生成class
  9. \'\'\'
  10.  
  11.  
  12. class weatherForecast():
  13. def __init__(self, weatherSite, path, endpng, savemodel):
  14. self.savemodel = savemodel
  15. if not os.path.exists(path):
  16. os.makedirs(path)
  17. def getPic(self):
  18. \'\'\'
  19. 获取资源
  20. \'\'\'
  21. print(\'获取pic\')
  22. d = pq(weatherSite)
  23. DomTree = d(\'#slideform #slide option\') # 获取DOM节点option 标签
  24. num = 100
  25. for bigpic in DomTree.items():
  26. pic = bigpic.attr(\'bigpic\') # 获取bigpic 属性指
  27. num += 1
  28. self.download(pic, \'a\' + str(num) + \'.png\') # 下载pic
  29. print(\'pic下载成功,共下载\' + str(num - 100) + \'png\')
  30. self.download(endpng, \'a1200.png\') # 下载end.png
  31. self.download(endpng, \'a1201.png\')
  32. self.download(endpng, \'a1202.png\')
  33. self.download(endpng, \'a1203.png\')
  34. def download(self, url, fname):
  35. \'\'\'
  36. 下载pic
  37. :return images size
  38. \'\'\'
  39. size = 0
  40. try:
  41. r = requests.get(url, timeout=3)
  42. file = open(path + fname, \'wb\')
  43. size = file.write(r.content)
  44. file.close()
  45. except:
  46. pass
  47. return size
  48. def getGIF(self):
  49. \'\'\'
  50. 生成gif
  51. \'\'\'
  52. images = []
  53. print(\'执行开始\')
  54. self.getPic() # 获取图片资源
  55. filenames = sorted(fn for fn in os.listdir(path) if fn.endswith(\'.png\'))
  56. if self.savemodel == 1: # imageio方法
  57. for filename in filenames:
  58. images.append(imageio.imread(path + filename))
  59. print(\'执行conversion操作\')
  60. imageio.mimsave(\'weather.gif\', images, duration=0.5, loop=1) # duration 每帧间隔时间,loop 循环次数
  61. print(\'完成……\')
  62. elif self.savemodel == 2: # PIL 方法
  63. imN = 1
  64. for filename in filenames:
  65. if imN == 1: # 执行一次 im的open操作,PIL在保存gif之前,必须先打开一个生成的帧,默认第一个frame的大小、调色
  66. im = Image.open(path + filename)
  67. imN = 2
  68. images.append(Image.open(path + filename))
  69. print(\'执行conversion操作\')
  70. im.save(\'weather.gif\', save_all=True, append_images=images, loop=1, duration=500,
  71. comment=b"this is my weather.gif")
  72. print(\'完成……\')
  73. \'\'\'
  74. 注:loop循环次数在浏览器有效果,用看图软件不起作用
  75. \'\'\'
  76. if __name__ == "__main__":
  77. weatherSite = "http://products.weather.com.cn/product/radar/index/procode/JC_RADAR_AZ9210_JB" # 上海南汇
  78. path = \'images/\' # png 图片存储位置
  79. endpng = \'http://images.cnblogs.com/likecs_com/dcb3688/982266/o_end.png\' # 因gif是循环播放,end png 区分新loop
  80. savemodel = 1 # 1:imageio保存图片, 2:PIL保存图片
  81. weatherForecast = weatherForecast(weatherSite, path, endpng, savemodel)
  82. weatherForecast.getGIF()
  83. sys.exit()

也可以修改gif尺寸大小,先修改png大小

  1. def download(self, url, fname):
  2. \'\'\'
  3. 下载pic
  4. :return images size
  5. \'\'\'
  6. size = 0
  7. try:
  8. r = requests.get(url, timeout=3)
  9. file = open(path + fname, \'wb\')
  10. size = file.write(r.content)
  11. file.close()
  12. # 修改图片大小,原:x=640*y=480 = 320*240
  13. ima = Image.open(path + fname)
  14. (x, y) = ima.size # read image size
  15. x_s = 320
  16. y_s = int((y * x_s) / x) # #calc height based on standard width
  17. out = ima.resize((x_s, y_s), Image.ANTIALIAS) # resize image with high-quality
  18. out.save(path + fname)
  19. except:
  20. pass
  21. return size

 

 

images目录

 

生成气象雷达图gif

 

脚步写好了,如何让别人也能访问呢,直接仍到公网IP的website目录就行了,然后写一个crontab定时脚步,每5分钟生成一次

  1. */5 * * * * python /home/wwwroot/www/web/static/weather/weather_forecast.py #每5分钟执行天气查询脚本

在这里,如果执行crontab定时脚步,代码生成的gif就要指定位置,否则生成的gif会在/root 目录里面

  1. imageio.mimsave(\'/home/wwwroot/www/web/static/weather/weather.gif\', images, duration=0.5, loop=1) # duration 每帧间隔时间,loop 循环次数

 

版权声明:本文为dcb3688原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/dcb3688/p/4608048.html