python抽帧及生成高质量的GIF图

对视频进行抽帧只需要两个模块即可:

opencv-python (cv2)

opencv-contrib-python

我们都知道视频有分辨率,即视频的宽度与高度,还有视频的帧速率,即每秒有多少帧。

对视频进行抽帧,有两种方式,一种是每秒抽取一帧,另一种是每秒所有帧的抽取。

import os
import cv2
import datetime
from pygifsicle import optimize def extract_frames(video_path, start_time, end_time, is_all=True):
"""
提取视频帧
:param video_path: 视频地址
:param start_time: 开始截取帧的时间
:param end_time: 结束截取帧的时间
:param is_all: 是否截图时间段所有帧,如果未来False,则每秒只截取1帧
:return: ideo_h, video_w, video_fps, out_path
""" first_frames = ''
filename = os.path.basename(video_path)
file_dir_name = os.path.dirname(video_path)
file_name = os.path.splitext(filename)[0]
cap = cv2.VideoCapture(video_path)
# 视频每秒帧数
video_fps = int(cap.get(cv2.CAP_PROP_FPS))
# 视频高度
video_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 视频宽度
video_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
# 视频时长
video_duration = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)/video_fps)
  
if start_time >= video_duration:
start_time = 1
if end_time >= video_duration:
end_time = video_duration
# 计算起始和结束帧
start_frame = int(start_time * video_fps)
end_frame = int(end_time * video_fps)
count = 0
proces_time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
out_path = f"{file_dir_name}/{file_name}/{proces_time}/"
os.makedirs(out_path)
  # 视频抽帧
while True:
ret, frame = cap.read()
if not ret:
break
if count == 0:
cv2.imwrite(out_path + f"frame_{count}.png", frame)
first_frames = out_path + f"frame_{count}.png"
# 如果已经超过结束帧,退出循环
if count >= end_frame:
break
# 如果当前帧在截取时间内,保存图片
if start_frame <= count:
# 如果需要抽取所有帧
if is_all is True:
cv2.imwrite(out_path + f"frame_{count}.png", frame)
# 如果是每秒只抽取一帧
if is_all is False and (count % video_fps == 0):
cv2.imwrite(out_path + f"frame_{count}.png", frame)
count += 1
cap.release()
return video_h, video_w, video_fps, out_path, first_frames

这里对视频的第一帧和指定的时间段做了抽帧,并返回视频的分辨率以及FPS。

接下来就是生成GIF图,图片都有了,合成GIF图很简单了:

用Pillow和imageio模块即可,如果还要压缩GIF的话,再安装pygifsicle这个模块即可:

def pic_to_gif(height, width, fps, pic_path, is_compress=True):
"""
图片转gif图
:param height: 生成gif图的高度
:param width: 生成gif图的宽度
:param fps: 生成gif图的帧率(每秒图片数)
:param pic_path: 需要生产gif图的图的地址
:param is_compress: 是否需要压缩
:return:
"""
img_path = []
for filename in os.listdir(pic_path):
if filename.endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tif', '.tiff')):
img_path.append(os.path.join(pic_path, filename))
images = [Image.open(file) for file in img_path]
cover_img = images[1].filename
# 设置 GIF 的尺寸和帧率
size = (width, height)
gif_file = f"{pic_path}01.gif"
with imageio.get_writer(gif_file, mode='I', fps=fps) as writer:
for image in images:
writer.append_data(image.resize(size))
# 步骤六:保存并关闭 GIF 文件
writer.close()
# def mimwrite(uri, ims, format=None, **kwargs):
# with imageio.mimsave(uri=gif_file, ims=images, fps=fps, loop=0) as write:
# 如果需要压缩GIF图
if is_compress is True:
optimize(gif_file, gif_file)
return gif_file, cover_img

imageio.get_writer 和 imageio.mimsave 方法都是一样的,是不是很简单!但对我来说,才开始。

因为用imageio生成GIF图,质量太不行,而且还比较大。

后来有找了很多生成GIF图的模块,比如moviepy,ImageMagick,都差强人意,值得说的是moviepy:

from moviepy.editor import VideoFileClip

video = VideoFileClip(video_path, verbose=True, has_mask=True)

clip = video.subclip(3, 6)

clip.write_gif("00.gif", program='ffmpeg', fps=4, tempfiles=False, fuzz=0)

"""
def write_gif(self, filename, fps=None, program='imageio',
opt='nq', fuzz=1, verbose=True,
loop=0, dispose=False, colors=None, tempfiles=False,
logger='bar'): program
Software to use for the conversion, either 'imageio' (this will use
the library FreeImage through ImageIO), or 'ImageMagick', or 'ffmpeg'. opt
Optimalization to apply. If program='imageio', opt must be either 'wu'
(Wu) or 'nq' (Neuquant). If program='ImageMagick',
either 'optimizeplus' or 'OptimizeTransparency'.
"""

moviepy 里的write_gif函数,可以传生成gif图的程序,比如imageio,ffmpeg,ImageMagick

也就是通过moviepy找到了解决方案,这几个程序我都尝试了一遍,当然,ffmpeg,ImageMagick都需要自己安装一下。

发现ffmpeg生成GIF图比imageio要好很多,imageio特别是遇到人脸等啥的,就像打了马赛克一样的。但ffmpeg整体均匀的模糊一样,马赛克不见了,但整体的GIF图质量还是没达到预期。ImageMagick也不行。

找了很多资料,还是在ffmpeg上找到了解决方案:

测试代码:

import subprocess as sp
from moviepy.compat import DEVNULL globalPalettePicPath = "D:\\thecover_project\\video_to_picture\\video_path\\000.png"
video_path = r"D:\thecover_project\video_to_picture\video_path\video1625112445881755141.mp4"
outFilePath = "D:\\thecover_project\\video_to_picture\\video_path\\1111111.gif" # video = VideoFileClip(video_path, verbose=True, has_mask=True)
# clip = video.subclip(3, 6)
# clip.write_gif("00.gif", program='ffmpeg', fps=4, tempfiles=False, fuzz=0)

popen_params = {"stdout": DEVNULL, "stderr": DEVNULL, "stdin": sp.PIPE}
command = f"ffmpeg -ss 3 -t 2 -i {video_path} -b:v 520k -r 29 -vf fps=29,scale=337:-1:flags=lanczos,palettegen -y {globalPalettePicPath}"
proc = sp.Popen(command, **popen_params)
proc.communicate()
proc.stdin.close()
command1 = f"ffmpeg -v error -ss 3 -t 2 -i {video_path} -i {globalPalettePicPath} -r 29 -lavfi fps=29,scale=337:-1:flags=lanczos[x];[x][1:v]paletteuse -y {outFilePath}"
# command1 = f"ffmpeg -ss 3 -t 2 -i {video_path} -r 29 -vf fps=29,scale=337:-1 {outFilePath}"
proc = sp.Popen(command1, **popen_params)
proc.communicate()
proc.stdin.close()

在生成GIF图前,先对视频进行全局采样,对每一帧的所有颜色制作一个直方图,并且基于这些生成一个调色板,原文详细介绍见这个地址:https://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html

 if video_h >= video_w:
video_w = 337
# video_w = 720
else:
video_w = 600
# video_w = 1280
global_palette_pic_path = f"{out_path}00.png"
gif_file = f"{out_path}01.gif"
# 命令通道参数,比如不打印显示日志信息等
popen_params = {"stdout": DEVNULL, "stderr": DEVNULL, "stdin": sp.PIPE}
# 定义全局调色板
command = f"ffmpeg -ss {start_time} -t {end_time-start_time} -i {video_path} -b:v 520k -r {video_fps} -vf fps={video_fps},scale={video_w}:-1:flags=lanczos,palettegen -y {global_palette_pic_path}"
proc = sp.Popen(command, **popen_params)
proc.communicate()
proc.stdin.close()
# 通过ffmpeg生成gif图
command1 = f"ffmpeg -v error -ss {start_time} -t {end_time-start_time} -i {video_path} -i {global_palette_pic_path} -r {video_fps} -lavfi fps={video_fps},scale={video_w}:-1:flags=lanczos[x];[x][1:v]paletteuse -y {gif_file}"
proc = sp.Popen(command1, **popen_params)
proc.communicate()
proc.stdin.close()
return first_frames, img_cover, gif_file

这里生成的GIF图,都进行了宽度压缩,竖屏就以宽度337来等比压缩。横屏就以600宽度等比压缩。比较符合网络传播。

好了,生成高质量的GIF图,摸索就到这!

以下是连接原文的转载:

使用 FFmpeg 的高品质 GIF

大约两年前,我尝试改进 FFmpeg 中对 GIF 编码的支持,使其至少像样。这尤其导致了 GIF 编码器中添加透明机制。虽然根据您的来源,这并不总是最佳的,但在最常见的情况下是这样。尽管如此,这只是为了防止编码器受到过多的羞辱。

但最近在Stupeflix ,我们需要一种为Legend 应用程序生成高质量 GIF 的方法,所以我决定再次致力于此。

本博文中介绍的所有功能都在FFmpeg 2.6中可用,并将在 Legend 应用程序的下一版本中使用(可能在 3 月 26 日左右)。

TL;DR:转到“用法”部分查看如何使用它。

初步改进(2013)

我们来观察一下2013年引入的透明机制在GIF编码器中的效果:

% ffmpeg -v warning -ss 45 -t 2 -i big_buck_bunny_1080p_h264.mov -vf scale=300:-1 -gifflags -transdiff -y bbb-notrans.gif
% ffmpeg -v warning -ss 45 -t 2 -i big_buck_bunny_1080p_h264.mov -vf scale=300:-1 -gifflags +transdiff -y bbb-trans.gif
% ls -l bbb-*.gif
-rw-r--r-- 1 ux ux 1.1M Mar 15 22:50 bbb-notrans.gif
-rw-r--r-- 1 ux ux 369K Mar 15 22:50 bbb-trans.gif

默认情况下启用此选项,因此您只需在图像有大量运动或颜色变化时才需要禁用它。

另一种实现的压缩机制是裁剪,这基本上是一种只允许重绘 GIF 的子矩形并保持周围不变的方法。对于电影来说,它很少有用。我稍后会再讨论这个问题。

但无论如何,从那时起,我在这方面就没有任何进展。虽然在上图中可能不太明显,但在质量方面存在不少缺陷。

256 色限制

您可能知道,GIF 的调色板仅限于 256 种颜色。默认情况下,FFmpeg 仅使用通用调色板,尝试覆盖整个颜色空间以支持最多种内容:

有序和误差扩散抖动

为了避免这个问题,使用了抖动。在上面的 Big Buck Bunny GIF 中,应用了有序拜耳抖动。它很容易通过其8x8交叉阴影线图案来识别。虽然它不是最漂亮的,但它有很多好处,例如可预测快速,并且实际上可以防止条带效应和类似的视觉故障。

您会发现大多数其他抖动方法都是基于错误的。其原理是,单一颜色错误(调色板中选取的颜色与预期颜色之间的差异)将遍布整个图像,导致帧之间出现“蜂拥效应”,即使在帧之间源完全相同的区域中也是如此。虽然这通常可以提供更好的质量,但它完全破坏了 GIF 的压缩:

% ffmpeg -v warning -ss 45 -t 2 -i big_buck_bunny_1080p_h264.mov -vf scale=300:-1:sws_dither=ed -y bbb-error-diffusal.gif
% ls -l bbb-error-diffusal.gif
-rw-r--r-- 1 ux ux 1.3M Mar 15 23:10 bbb-error-diffusal.gif

更好的调色板

提高 GIF 质量的第一步是定义更好的调色板。 GIF格式存储了一个全局调色板,您可以为一张图片(或子图片;每一帧叠加在前一帧上,但可以以更小的尺寸以特定偏移量叠加)重新定义调色板。每帧调色板仅取代一帧的全局调色板。一旦您停止定义调色板,它就会退回到全局调色板。这意味着您无法像您想做的那样为一系列帧定义调色板(通常在每个场景更改时定义一个新调色板)。

换句话说,您必须遵循一个全局调色板或每帧一个调色板的模型。

每帧一个调色板(未实现)

我最初是从实现每帧调色板的计算开始的,但这有以下缺点:

  • 开销:256 色调色板为 768B,它不是 LZW算法机制的一部分,因此不会被压缩。由于必须按每一帧存储它,这意味着 25 FPS 素材的开销为 150 kbits/sec。但它大多可以忽略不计。
  • 我最初的测试是由于这些调色板的变化而产生亮度闪烁效果,这根本不漂亮。

这是我没有遵循该路径并决定计算全局调色板的两个原因。现在我回想起来,可能需要重试该方法,因为颜色量化的状态比我最初的测试更好。

还可以在帧范围的每个帧处存储相同的调色板(通常在场景变化时,如前面提到的)。或者更好,仅针对发生变化的子矩形。

所有这些都留给读者作为练习,欢迎补丁。如果您对此感兴趣,请随时与我联系。

一个全局调色板(已实现)

拥有一个全局调色板意味着 2 遍机制(除非您愿意将所有视频帧存储在内存中)。

第一遍是计算整个演示文稿的调色板。这就是新的调色板生成过滤器发挥作用的地方。该滤镜对每帧的所有颜色制作直方图,并从中生成调色板。

关于技术方面的一些琐事:过滤器正在实现 Paul Heckbert 的帧缓冲区显示彩色图像量化 (1982)论文中的算法的变体。以下是我记得所做的差异(或论文中未定义行为的特殊性):

  • 它使用全分辨率颜色直方图。因此,该过滤器没有像论文中建议的那样使用下采样 RGB 5:5:5 直方图作为关键,而是使用哈希表来存储 1600 万种可能的 RGB 8:8:8 颜色。
  • 盒子的分割仍然是在中点处进行,但是根据盒子中颜色的方差来选择要分割的盒子(颜色方差较大的盒子将被优先选择为截止) )。
  • 据我所知,这在论文中没有定义,但框中颜色的平均值是根据颜色的重要性来完成的。
  • 当沿轴(红、绿或蓝)分割盒子时,在相等的情况下,绿色优先于红色,而红色又优先于蓝色。

所以无论如何,这个过滤器会进行颜色量化,并生成调色板(通常保存到文件中PNG)。

它通常看起来像这样(放大):

颜色映射和抖动

然后,第二遍由调色板使用过滤器处理,正如您从名称中猜测的那样,它将使用该调色板生成最终的颜色量化流。它的任务是在生成的调色板中找到最合适的颜色来表示输入颜色。您也可以在此处决定使用哪种抖动方法。

再说一些技术方面的琐事:

  • 虽然原始论文仅提出了一种抖动方法,但滤波器实现了其中 5 种。
  • 就像 一样palettegen,颜色分辨率(将 24 位输入颜色映射到调色板条目)是在不破坏输入的情况下完成的。它是通过Kd Tree的迭代实现(显然 K=3,每个 RGB 分量一个维度)和缓存系统来实现的。

使用这两个过滤器将允许您像这样编码 GIF(单个全局调色板,无抖动):

用法

使用相同的参数手动运行 2 个通道可能会有点烦人,需要调整每个通道的参数,因此我建议编写一个简单的脚本,例如:

#!/bin/sh

palette="/tmp/palette.png"
filters="fps=15,scale=320:-1:flags=lanczos" ffmpeg -v warning -i $1 -vf "$filters,palettegen" -y $palette
ffmpeg -v warning -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y $2

...可以这样使用:

% ./gifenc.sh video.mkv anim.gif

filters变量包含在这里:

  • 每秒帧数的调整(减少到 15 可能会导致视觉上的抖动,但会使最终的 GIF 更小)
  • 使用lanczos缩放器而不是默认的缩放器(bilinear当前)。建议您使用lanczos或重新缩放,bicubic因为它们远远优于bilinear。如果不这样做,您的输入很可能会更加模糊。

仅提取样本

您不太可能对完整的电影进行编码,因此您可能会想使用-ss-t(或类似)选项来选择片段。如果您这样做,请务必将两者都作为输入选项(在 之前-i)。例如:

#!/bin/sh

start_time=12:23
duration=35
palette="/tmp/palette.png"
filters="fps=15,scale=320:-1:flags=lanczos" ffmpeg -v warning -ss $start_time -t $duration -i $1 -vf "$filters,palettegen" -y $palette
ffmpeg -v warning -ss $start_time -t $duration -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y $2

如果不这样做,至少在第一遍中会导致问题,其中输出永远不会超过一帧(调色板),因此不会达到您想要的效果。

一种替代方法是使用流复制来预提取要编码的样本,例如:

% ffmpeg -ss 12:23 -t 35 -i full.mkv -c:v copy -map 0:v -y video.mkv

如果流副本不够准确,您可以添加修剪 过滤器。例如:

filters="trim=start_frame=12:end_frame=431,fps=15,scale=320:-1:flags=lanczos"

充分利用调色板一代

现在我们可以开始看看有趣的部分了。在palettegen过滤器中,您想要进行的主要且可能唯一的调整是选项stats_mode 。

此选项基本上允许您指定您是对整个/整体视频更感兴趣,还是仅对正在移动的内容更感兴趣。如果使用stats_mode=full (默认),所有像素都将成为颜色统计的一部分。如果使用 stats_mode=diff,则仅考虑与前一帧不同的像素。

注意:要向过滤器添加选项,请像这样使用它: thefilter=opt1=value1:opt2=value2

以下是一个示例来说明它如何影响最终输出:

 

第一个 GIF 正在使用stats_mode=full(默认)。整个演示文稿的背景不会改变,因此天空的颜色受到了很多关注。另一方面,移动文本最终的颜色子集非常有限。结果,文本的淡出受到了影响:

另一方面,第二个 GIF 使用stats_mode=diff,这有利于移动的内容。事实上,文本的淡出要好得多,但代价是天空中出现抖动故障:

充分利用颜色映射

paletteuse过滤器有更多的选项可供使用。最明显的一个是抖动(dither选项)。唯一可用的可预测抖动是bayer,所有其他抖动都是基于误差扩散的。

如果您确实想使用bayer(因为您有高速或尺寸问题),您可以使用bayer_scale降低或增加其剖面线图案的选项。

当然,您也可以使用 来完全禁用抖动 dither=none

关于误差扩散抖动,您需要使用 floyd_steinbergsierra2sierra2_4a。有关这些的更多详细信息,我将您重定向到DHALF.TXT

对于懒人来说,floyd_steinberg是最流行的之一,并且sierra2_4a是(并且是默认的)的快速/较小版本sierra2,通过 3 个像素而不是 7 个像素进行扩散。heckbert是我之前提到的论文中记录的一个,并且只是包含为一个参考(你可能不需要它)。

以下是不同抖动模式的小预览:

原始(31.82K): 

dither=bayer:bayer_scale=1(132.80K): 

dither=bayer:bayer_scale=2(118.80K): 

dither=bayer:bayer_scale=3(103.11K): 

dither=floyd_steinberg(101.78K): 

dither=sierra2(89.98K): 

dither=sierra2_4a(109.60K): 

dither=none(73.10K): 

最后,在尝试了抖动之后,您可能有兴趣了解该选项diff_mode。引用文档:

只有变化的矩形才会被重新处理。这类似于 GIF 裁剪/偏移压缩机制。如果仅图像的一部分发生变化,则此选项对于提高速度很有用,并且具有一些用例,例如将误差扩散抖动的范围限制为限制移动场景的矩形(如果场景不发生变化,则它会导致更具确定性的输出)变化不大,因此移动噪音更少,GIF 压缩效果更好)。

或者换句话说:如果您想在图像上使用误差扩散抖动作为背景,即使它是静态的,请启用此选项来限制误差在整个图片上的传播。这是一个相关的典型案例:

请注意,只有当顶部和底部文本同时移动时(即,在此处的最后一帧中),猴子脸上的抖动才会发生变化。

python抽帧及生成高质量的GIF图的更多相关文章

  1. C#放缩、截取、合并图片并生成高质量新图的类

    原文:C#放缩.截取.合并图片并生成高质量新图的类 using System;using System.Drawing;using System.Drawing.Imaging;using Syste ...

  2. atitit.thumb生成高质量缩略图 php .net c++ java

    atitit.java thumb生成高质量缩略图 php .net c++ 1. 图像缩放(image scaling)---平滑度(smoothness)和清晰度(sharpness) 1 2.  ...

  3. Python高质量缩放切图,抗锯齿

    最近刚接触Python,以迅雷不及掩耳盗铃之势(只是迫不及待)应用到工作中去了之前用 cmd+photoshop做批量图像处理(缩放切片),在执行效率(速度)上和灵活度上有很大限制,遂转战Python ...

  4. C#剪切生成高质量缩放图片

    /// <summary> /// 高质量缩放图片 /// </summary> /// <param name="OriginFilePath"&g ...

  5. <1>Python生成高质量Html文件:Pyh模块+Bootstrap框架

    一,介绍 QQ交流群:585499566 本文的目的是怎么使用Pyh+Bootstrap快速生成简约,大方,清新的Html页面,涉及到的技能:Python小白技能,Pyh会阅读中文文档,Html基础, ...

  6. Highcharts结合PhantomJS在服务端生成高质量的图表图片

    项目背景 最近忙着给部门开发一套交互式的报表系统,来替换原有的静态报表系统. 老系统是基于dotnetCHARTING开发的,dotnetCHARTING的优势是图表类型丰富,接口调用简单,使用时只需 ...

  7. MPlayer-ww 增加边看边剪切功能+生成高质量GIF功能

    http://pan.baidu.com/s/1eQm5a74 下载FFmpeg palettegen paletteuse documentation 需要下载 FFmpeg2.6 以上 并FFmp ...

  8. ASP.NET 画图与图像处理-生成高质量缩略图

    http://www.cftea.com/c/2007/08/SG9WFLZJD62Z2D0O.asp

  9. 编写高质量代码--改善python程序的建议(六)

    原文发表在我的博客主页,转载请注明出处! 建议二十八:区别对待可变对象和不可变对象 python中一切皆对象,每一个对象都有一个唯一的标识符(id()).类型(type())以及值,对象根据其值能否修 ...

  10. Effective Python之编写高质量Python代码的59个有效方法

                                                         这个周末断断续续的阅读完了<Effective Python之编写高质量Python代码 ...

随机推荐

  1. [学习笔记] CentOS + .Net后端常用的中间件工具安装

    Redis 5.0+ 官方文档:https://redis.io/download/#redis-downloads sudo yum install redis RabbitMQ 3.7.11+ 官 ...

  2. Android TextView设置某段文字可点击

    初次进入app,需要有个勾选隐私协议的UI,其中的隐私协议文字点击是可跳转到新页面对隐私协议机型展示 这里选择使用Android自带的SpannedString来设置TextView的文字内容即可设置 ...

  3. MySQL(表相关操作)

    一 存储引擎 日常生活中文件格式有很多,并且针对不同的文件格式会有对应不同存储方式 和处理机制(txt.word) 针对不同的数据应该有对应的不同的处理机制来存储 存储引擎就是不同的处理机制 MySQ ...

  4. golang 运行时死锁排查和检测

    当运行的系统发生goroutine等待获取锁时间超过预期时,判定为发生了死锁.因目前代码中使用了一些公开的锁实例,调用链也比较长,对问题排查带来了很大困扰.为了便于问题排查,需要借助工具来实现. 1. ...

  5. 记录--ThreeJs手搓一个罗盘特效

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 先上效果 前言 最近在学Three.js.,对着文档看了一周多,正好赶上码上掘金的活动,就顺便写了一个小demo,手搓一个罗盘特效. 太极 ...

  6. 一招搞定进制转换--java篇

    java中进制转化只需要记住这两个方法,后续再遇到进制转换的问题,轻松破解! 进制转换的核心就是: 其他进制--->十进制--->其他进制 1.其他进制转成十进制 valueOf() 方法 ...

  7. archlinux xfce修改桌面字体颜色

    参照 https://forums.linuxmint.com/viewtopic.php?t=341804 1.大于等于4.14的版本则在主文件夹的 .config 文件夹 gtk-3.0 中,创建 ...

  8. 《写给程序员的Python教程》阅读随笔---python禅学(Zen_of_python)

    Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Comp ...

  9. Python爬虫爬取ECVA论文标题作者摘要关键字等信息并存储到mysql数据库

    网站截图: 源代码: 1 import re 2 import requests 3 import pymysql 4 from bs4 import BeautifulSoup 5 import l ...

  10. 区别对比 Python、Perl、VB、Ruby、C/C++、C# .Net、PHP、Java… 等多编程语言

    1. 编程语言类型:首先,Python.C/C++.Java 都是强类型的编程语言.强类型的编程语言定义如下: 强类型的编程语言是一种强制类型定义的编程语言,即一旦某一个变量被定义类型,如果不经强制转 ...