异步社区《基于Python的金融分析与风险管理(第2版)》电子版免费页面爬虫攻略
一、任务描述
地址:https://www.epubit.com/bookDetails?id=UB77f4a1b70747e
异步社区《基于Python的金融分析与风险管理(第2版)》电子版免费页面下载。
异步社区的主页上搜到本书详情页面后,下拉可看到此书提供的免费电子书部分。
点开后,可以看到,这更像是一个内嵌在网页中的电子书浏览插件,右侧一排按钮可以查看目录,调整字号等。中间部分是电子书的页面。
我们编写本爬虫的目的,就是将这些电子书的页面自动爬下来。省去手动下载的繁琐工作,提高效率。
二、前期准备
2.1爬取格式
通过右键另存为进行测试可以发现,每一页都是一个jpg文件,是一张图片。
2.2网址分析
他们的网址类似于:
https://cdn.ptpress.cn/pubcloud/5B0A982E/ubook/UB77f4a1b70747e/pdfEbook/82dca929-8982-464d-a29b-ed666e63321d.jpg
https://cdn.ptpress.cn/pubcloud/5B0A982E/ubook/UB77f4a1b70747e/pdfEbook/cf0444a3-5c47-4fce-8c24-b8c1e6cfa20d.jpg
https://cdn.ptpress.cn/pubcloud/5B0A982E/ubook/UB77f4a1b70747e/pdfEbook/cf717f5d-8ef4-4c63-be0d-8048be76b98d.jpg
非免费的图书图片的页面和网址类似如下:
https://cdn.ptpress.cn/pubcloud/bookImg/A20210127/20211015A2B3BE0A.jpg
通过上述测试和分析可以看出,免费图书的网址看似很有规律
都是:https://cdn.ptpress.cn/pubcloud/5B0A982E/ubook/UB77f4a1b70747e/pdfEbook/ 加上一个长码的名字。
实际上又找不出规律,因为后面的这个图片名字是无规律可循的。
所以,要找到链接到这些图片的母链接就尤为关键。
三、网页分析与链接规律解析
首先派上用场的就是“开发者工具”,主流的浏览器如chrome,firefox,360,都自带开发者工具,帮助分析网页信息。快捷键统一为:F12.
3.1静态网页思维尝试
首先,我们按照静态网页思维尝试找到链接簇,再利用正则表达式爬取这些链接达到爬虫目的。
随便打开目录->扉页,
在开发者工具中点击“元素”(英文版“Elements”),Ctrl+F,在下方出现的查找框中,输入扉页的两页电子书的图片下载地址。
https://cdn.ptpress.cn/pubcloud/5B0A982E/ubook/UB77f4a1b70747e/pdfEbook/82dca929-8982-464d-a29b-ed666e63321d.jpg
https://cdn.ptpress.cn/pubcloud/5B0A982E/ubook/UB77f4a1b70747e/pdfEbook/cf0444a3-5c47-4fce-8c24-b8c1e6cfa20d.jpg
会发现,在页面元素中,都且仅存在着一个元素<div class="signleImg">
来对应。
也就是说,只要能找到这一个页面的网址就可以顺藤摸瓜,找到这一页面的一个或多个元素<div class="signleImg">
,从而找到对应的图片下载地址了。
这一页面的网址为:
https://www.epubit.com/onlineEbookReader?id=126e68580c864d68ac7205c4fd9a55a1&pid=78c6d7a124e04ced8c271bf65126fb6f&isFalls=true
依次的,还可以看到其他页面的网址,例如“内容摘要”的网址:
https://www.epubit.com/onlineEbookReader?id=2bc5be337a7949ffaa0e5886b0b4c524&pid=78c6d7a124e04ced8c271bf65126fb6f&isFalls=true
“作者简介”的网址为:
https://www.epubit.com/onlineEbookReader?id=e50c5f575082449e9d688eaf32469bc3&pid=78c6d7a124e04ced8c271bf65126fb6f&isFalls=true
因此,如果能在上一级的页面中找到这些网址簇,就可以解决问题了。
于是,打开上一级页面,
输入任意一个页面的网址,很可惜,并未发现。这也正式宣告,此路不通,正所谓近在眼前,却远在天边。人看着很简单,程序就是找不着。
3.2动态网页思维尝试
很明显,阅读页中的信息,并不是通过上一级的页面中明码写出来的各种网址来获取的,而是通过点击:目录,上一节,下一节这些按钮来获取并更新页面的。这些按钮的点击背后做了哪些事情,需要你掌握一定的前后端编程知识和一些网络编程基本原理。如果你没有,只会一些python怎么办?“开发者工具”给我们提供了一些途径和方法。
3.2.1寻找imgUrl
打开电子书阅读页面,打开开发者工具,切换到“网络”页(英文“Network”),点击“清除”按钮,清空网络活动记录,接下来,点击“目录”,点击“扉页”。如果在这些操作前,当前的页面本就在“扉页”页。则开发者工具会记录两个操作。点击这两个操作,会发现,右边的预览是空的,说明并不是有效信息。过一会会出现两条自动保存的操作的记录。
清空一下,再试试其他的页面,比如“内容提要”。
这时候出现了一系列的操作记录,可以从第一个开始利用键盘上下键来查找有价值的操作。盯着预览框。当然,也不全是撞大运,这些操作的名字也是有一定的提示性的。比如后缀是js的那些文件可以略过了。有经验的程序员会重点关注get开头的操作,以及content,id,ebook,image这样的关键词来查找。很幸运,我找到了一条叫做:
getContentsByFolderId?folderId=2bc5be337a7949ffaa0…4&projectId=78c6d7a124e04ced8c271bf65126fb6f&src=
的操作。该操作的反馈预览中欣喜的发现了一个叫做imgUrls的项,其中的第0个项恰恰是我们想要的图片地址。
PS:这里要了解的知识背景是:对于动态网页而言,每一次网络请求,服务器端都会返回一个Json对象,携带着结构化的信息。Json对象可以理解为一个可以嵌套的“键值对”数组。是传统的重量级结构化标记语言文件xml的轻量级变种,是现在最主流的,最高效的信息传输载体结构。可以通过点击“预览”旁边的“响应”(英文版“Response”)来一探Json真容。
在此操作下,打开“标头”页(英文版“Headers”),会看到一个请求 URL:
https://www.epubit.com/pubcloud/content/front/getContentsByFolderId?folderId=2bc5be337a7949ffaa0e5886b0b4c524&projectId=78c6d7a124e04ced8c271bf65126fb6f&src=
这个URL就是获得我们想要的Json对象的请求。只要利用Python程序,解析该请求URL,就可以得到json对象,再解析json对象,就可以提取到想要的imgUrls了。
那么问题来了,如何才能得到这个网址呢?我们当然知道是因为点击了“目录”->“内容提要”,爬虫如何嗅到呢?
继续测试其他的几个页面,如:
“作者简介”页的请求URL为:
请求 URL:
https://www.epubit.com/pubcloud/content/front/getContentsByFolderId?folderId=e50c5f575082449e9d688eaf32469bc3&projectId=78c6d7a124e04ced8c271bf65126fb6f&src=
“前言”页的请求URL为:
请求 URL:
https://www.epubit.com/pubcloud/content/front/getContentsByFolderId?folderId=e327f6ad01a54babad95397d4e75eff5&projectId=78c6d7a124e04ced8c271bf65126fb6f&src=
等等。
似乎规律已经浮现:
(1)projectId是一个固定的值,应该是本书的一个统一的id。
(2)其余部分都是定值。
(3)folderId的值是变化的。
只要找到folderId的值,就可以成功拼出请求URL,从而得到下载图片的链接地址。
3.2.2寻找folderId
接着在操作记录中寻找蛛丝马迹。功夫不负有心人,在“前言”页的操作中,一个叫做ebookFolderTree?projectId=78c6d7a124e04ced8c271bf65126fb6f的操作,在预览页中可以看到
有一个data项里有12个分项,仔细比对你就会发现,整好对应着目录的十二个子目录。其实名字已经暗藏玄机,ebookfoldertree就是电子书目录树的意思。打开第六个分项,其中的id子项的值,整好就对应着“前言”页的folderId的值。离成功越来越近了,接下来要看看,该操作对应的请求Url是不是一个有规律的,甚至是固定的URL。打开“标头”页,则看到:
请求 URL:
https://www.epubit.com/pubcloud/content/front/ebookFolderTree?projectId=78c6d7a124e04ced8c271bf65126fb6f
该URl的projectId,就是本书的统一Id号。
可以继续考察其他页的ebookfoldertree操作,欣喜的发现,均为相同的请求URL。
这意味着:该请求URL,可以解析出所有的12个子目录的folderId,从而进一步获得相应的imgUrls,再保存这些图片就能完成爬取工作了。
至此,我们的网页分析与链接规律解析工作已经完成。接下来就是利用Python的各种神器,八仙过海各显神通的写出爬虫了。
四、编写Python爬虫
4.1 解析ebookFolderTree返回数据,获取folderIds
首先,引入必备的包
#用于处理网络请求的包
import requests
#用于解析json数据的包
import json
接下来,利用get方法,从服务器获取ebookFolderTree的json数据。
#利用get方法,从服务器获取ebookFolderTree的json数据
res = requests.get("https://www.epubit.com/pubcloud/content/front/ebookFolderTree?projectId=78c6d7a124e04ced8c271bf65126fb6f")
ebookFolderTree = json.loads(res.text)
接下来,解析ebookFolderTree的json数据,并逐层解析子目录,将所有的folderid记录在案。
#解析json数据
#1.拿到data键对应的列表
data = ebookFolderTree['data']
#2.初始化folderids用来存储从ebookFolderTree获取的folderid集。
folderids = []
#3.从预览的json数据可以看出,一共有12个列表项,对应了书的12个目录分项,其中每一列表项中的id键对应的值就是folderid。得到它。
#遍历12个列表项
for n in range(12):
#将第n个data分项中id键对应的值,也即folderid值添加到forlderids中。
folderids.append(data[n]['id'])
#如果有子目录(对应的键为:children),则应继续处理子目录中的folderid。
#有一些目录有子目录,甚至是多级子目录。通过观察发现,含有子目录的章节,根目录有folderid对应的是大章节(基础篇,中级篇,高级篇)的章首页的图片。
#二级子目录有folderid对应的是某一章的首页图片,三级子目录对应的是某一节的所有下级节的图片(往往不是一张图片),遍历到这里就可以了。四级子目录则和三级子目录重复。
#可以参考观察目录基础篇(对应第9个分项)的children结构。
#如果有二级子目录
subfolder = data[n]['children']
if subfolder != []:
#遍历子目录
for sf in subfolder:
#二级子目录ID存储至folderids以备下载图片
folderids.append(sf['id'])
#如果有三级子目录
ssubfolder = sf['children']
if ssubfolder != []:
#遍历三级子目录
for ssf in ssubfolder:
#将三级子目录ID存储至folderids以备下载图片
folderids.append(ssf['id'])
4.2利用folderId列表获取imgUrls,并下载图片,保存
利用folderids列表,拼装操作getContentsByFolderId?folderId=xxxxxxxxxx的请求URL,从而在返回的json数据中解析并获取imgUrls列表。再将imgUrls对应的图片资源获取后,写入本地文件,保存为图片。
#利用folderids列表,拼装操作getContentsByFolderId?folderId=xxxxxxxxxx的请求URL,从而在返回的json数据中解析并获取imgUrls列表。
#下载保存的文件名imgnameid
imgnameid = 1
#逐一拼接标头请求URL,从返回的json数据中提取imgUrls
for folderid in folderids:
#利用folderID拼接请求URL,获取res
res = requests.get("https://www.epubit.com/pubcloud/content/front/getContentsByFolderId?folderId={folderid}&projectId=78c6d7a124e04ced8c271bf65126fb6f&src=".format(folderid= folderid))
#装载json
bookcontent = json.loads(res.text)
#获取bookcontent Json数据的data键对应的值
data = bookcontent['data']
#此处注意,如果不是免费的,则返回的msg值是“没有权限”。
#如果不是“没有权限”,也就是说:是免费的,那就开始遍历imgUrls下载
#if bookcontent['msg'] == "成功":
if bookcontent['msg'] != "没有权限":
#从data中取得imgUrls键对应的列表
imgUrls = data['imgUrls']
#遍历imgUrls列表,下载图片
for imgUrl in imgUrls:
#获取图片资源
img = requests.get(imgUrl)
#保存至指定文件夹
with open("D:\\桌面\\testjpg\\{id}.jpg".format(id= imgnameid),"wb") as fp:
fp.write(img.content)
imgnameid += 1
这个加上注释一共六十行的小程序,就完成了对电子书《基于Python的金融分析与风险管理(第2版)》的免费部分的下载保存。当然,这要感谢异步社区并未开启反爬虫机制。同时,该程序只要稍加改进,整理,抽象出稍微通用的接口,就可以下载该网站的其他书籍的免费电子版了。那是另一部分的工作,此处不再赘叙。
五、实验结果
见证奇迹的时刻:
不需要前后端技术基础,只需要简单的python基础知识,手把手教你做爬虫。
你,学会了吗 :)