爬取Bing每日壁纸

前言

最近做了一个爬虫小项目,爬取Bing每日壁纸。经过了上一次的爬虫学习,学会了分析基本的网页。因此这次依然是抓取JSON数据解析,相对于上一次的代码,用了比较Pythonin的写法,其中运用了速度大大地加快了。

1 . Bing每日壁纸的获取

必应壁纸右键无法下载

于是,右键检查元素定位到图片div布局,却发现没有显示出图片的URL,即使分析了前后的html代码依然无法找到

div布局无法显式指出

按照以往的经验,这样子的情况说明,很有可能需要Ctrl + U检查源代码才能发现网页代码规律,于是便打开源代码检查,再一次感受到了凌乱的画风…

令人一脸懵逼的JavaScript代码

了解到Bing首页右下角一排,有两个和Button用来切换壁纸,由于每次切换布局不变,仅仅是壁纸换了,因此每次点击就是在请求新的壁纸数据,然后加载。

于是,按F12进入检查模式控制台,选择Network中的XHR,然后刷新当前页面,终于发现Request URL

打开Request URL发现,这就是一个JSON数据!而,且请求的数据信息非常清晰明了!

而我需要的信息就是这两条

url中的参数提取出来,加上头部,生成完整的网址

浏览器中打开这个网址,果然就是我们需要的!

打开图片地址

到了这一步,已经算成功了一半!

接下来我继续分析每次Request URL的规律,多次点击首页右下角的Button,查看请求的数据,果然发现一大Request URL

大量的Request URL

Request URL的值呈现一定的规律

通过字符串比较,以及测试发现以下2个重要参数:

idx:第几张照片,取值范围 [ -1 , 7 ] ,其中-1参数表示明天的壁纸,参数表示今天的壁纸,其他的则表示n天前的壁纸,该通项最大获取到7天前的壁纸

n: 一次性获取n组JSON数据,从idx开始数起的n天前的JSON数据总和。

其他参数经测试,没有必要性。因此,我们的精简版的Request URL的通项是

测试发现,以这种通项最多获取的图片数目为16张

代码实现

至此,以这种方法已经可以达到我的目的了。(我之所以强调以这种方法的意思是,当然还有其他方法,只不过那种方法技术含量有点低,不适合拿来学习探索。当然了实现效果是很不错的,还可以获取大量的壁纸!以后有机会写个GUI项目,可以考虑另外一种方法实现)

但是我转念一想,为啥Bing就是不肯让我下载它的壁纸咧?!肯定不止我一个人想下载它的壁纸,按理来说它应该提供下载的方法呀,于是,我便在它的首页上找呀找呀……终于,当我切换到Bing国际版的时候,发现了下载的地方!

切换到国际版有下载的地方

但是,这种方法就显得不是很方便了,而且只能手动一张张下载8张照片而已。所以如果你是本篇文章的读者,然后又看不懂爬虫代码,又想换壁纸的,那么就试试这种不错的方法吧。

2 . 核心代码

多进程

首先看一下关于,所谓的的由来与定义

最早的操作系统是没有“进程“这个概念的,比如DOS。正如其名“Disk Operating System”,DOS主要的任务就是管理一下磁盘,并把BIOS和硬件做一点抽象。在上面开发的程序,其实是直接跟CPU打交道的,程序最终会编译或者解释成CPU指令并被执行。

这个系统有个最大的问题,就是同时只能执行一个程序。这样对于用户使用无疑太不友好了,我想一边听音乐一边写代码都做不到!怎么办呢?CPU就像一个无脑的工人,在它那里根本没有“程序”的概念,只负责处理“指令”,所以如果我们程序不做点事情,那么好像无论如何都无法实现“多个程序同时执行”吧?

于是,就有了“分时多进程”的操作系统。操作系统把想要执行的程序管理起来,并且按照一定的规则,让它们都得到执行。因为CPU执行很快,所以对用户看起来它们就像同时在执行一样,这就是所谓的“进程“。

简而言之,进程是程序的实体

----- 摘自 https://github.com/code4craft/os-learning/blob/master/posts/ch2.md

因此,所谓的简单地理解便是。

在Python中提供了与模块来实现,但由于仅适用于Linux或UNIX系统,因此在Windows OS下无法使用。不过,模块是跨平台的,因此可以编写跨平台的多进程代码。

以上代码,我用的是创建一个进程池Pool的方法来实现多进程的,这样就形成了一个进程队列一样,当进程池未满,可以添加新的进程到进程池中;当进程池已满,则等待Pool中的某个进程结束,再添加进去。

其中,Pool()默认大小是CPU核数,虽然我的电脑用软件CPU-Z检测出核心数是2,但是指定参数process=2时,却只发挥出一半的速度;而默认参数Pool()指定参数Pool(process=4)则发挥出来最大运行速度。

CPU-Z检测结果

因此,个人觉得,一般情况下考虑到代码移植性问题,还是默认参数比较好。

本段代码中,还有一个关键点,那就是方法

其中,close()方法是Pool对象特有的,一般情况下,手动创建单进程是与方法配合使用

Pool对象调用join()方法会,调用join()方法之前必须先调用close()方法,调用close()方法后了。

使用yield返回结果的函数

可以算是Python里面的一个黑魔法了,它非常有意思,真要深入研究一番估计得专门写一篇,但这不是这篇笔记的重点,因此在此处只是简单地应用一下的特点吧

yield修饰的函数,用于每次返回一个结果。每次调用该函数,会从上一次yield返回处开始执行后面的代码,然后遇到yield再次返回。

简而言之,yield返回的函数,就不在是一个简单的函数了,而是一个generator

来看一个yield返回的函数

程序结果显示,被yield返回的函数,其本质是

那么这样做有什么好处呢?答案是,减小内存的使用,有效简化代码(简化代码功能此处不明显)。

有时候,当我们需要函数处理大量的数据时,并不能等函数将所有结果计算完毕再把结果集合(此处的集合不是指Python中的set数据类型,而是数学中的集合概念)返回。这样做有2个非常明显的坏处

当结果集合非常大的时候,会非常消耗内存。因为所有的代码程序都是在内存中运行的,如果数据量过大,好比处理1T的数据,几个G的内存是远远不够的。

当被调函数需要计算较长时间时,若一定要等待最终结果返回,在时间效率上会非常低,这会导致后面的主调函数大部分时间都在等待被调函数。

而一次只返回一个结果,在内存中也只暂时保留一个返回结果,在时间效率上能够让主调函数先进行下一步计算(有点主调函数与被调函数并行的感觉),不需要等待被调函数。

OS模块创建文件夹

OS模块创建文件夹有挺多方法的,经过我多次试验,下面两个方法比较好用

os.path.exists(path): 检查path路径是否存在,如:os.path.exists('D:/Bing'),判断D盘路径下是否有一个Bing的目录文件夹

os.makedirs(path): 创建多级目录,如:os.makedirs('D:/Bing/image'),创建一个文件夹名为image,在D盘下Bing文件中

3 . 完整源代码与运行结果

单进程版本

单进程版本结果

多进程版本

多进程版本运行结果

对比结果,我们发现多进程版本速度是单进程版本速度的3倍!

4 . 打包成Windows下的.EXE文件

使用第三方库,将Python程序打包成Windows OS下的.EXE文件。

安装Pyinstaller,网上很多文章说在Python 3.5以上版本会报各种错误。但是经过我试验,现在的版本已经不会报各种错误了,直接在命令行下安装便是

然后,准备一张.ico格式的图片,用于生成文件

当我满怀欢喜开始运行程序时,发现单进程版本没任何问题,而运行多进程版本…电脑居然直接死机了!!!What?!!!

刚开始还以为是参数错误,后来反复检验发现,参数没有错误。生成的EXE文件始终都会造成死机,此时电脑已经强制关机了好几次了,真是心疼我电脑…

在这个神奇的404不存在网站找到了答案(https://g.kfd.me/webhp?hl=zh-CN&ictx=2&sa=X&ved=0ahUKEwjOlNW37ILbAhVFGpQKHY3lAesQPQgD),在一篇博客中发现了满意的答案。

按照博客指示,先创建了一个自定义模块,这里需要注意的是要将multiprocess_package_win放到C:\Users\zlj\AppData\Local\Programs\Python\Python36\Lib(说白了就是python的Lib包中,视个人电脑而定,不一定是我的这个路径),然后再去导入它。

这段代码大概的意思是,先检查出程序运行的平台if sys.platform.startswith('win'),然后再导入模块import multiprocessing.popen_spawn_win32 as forking,然后判断出是在Windows platform后,创建一个类(类里面的一些方法作用暂时不是很清楚)。

然后主程序部分,并不需要向网上(https://blog.csdn.net/Xiong_Big/article/details/54614231)说的那样需要导入模块import multiprocess_package_win。我觉得原因就在于multiprocess_package_win.py文件中try…except有关。

单进程EXE文件

多进程EXE文件

下载的图片

OneMoreThing…

分享一首好歌

《大学之路》已经全部看完了,但是读书笔记还没开始写…

分享一本最近在看的书,《什么是数学 · 对思想和方法的基本研究》,是著名的哥根廷学派的成员R · 柯朗,H · 罗宾,I · 斯图尔特所著,虽然目前只看到数论章节,但这种深入浅出的的好书(而且还是数学书),值得好好研读一番。

素数有无穷多个的欧几里得反证法

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180513G1L7MI00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券