做离线网站爬虫吃过的亏

本文系爬虫初学者胡言乱语,不入方家法眼,为免贻笑大方,如若强行阅读,后果自负!

起因

最近在学习使用python做网络爬虫,看教程挺简单的,使用 requests 简单几行代码就能够把网页内容爬下来,甚是惬意。刚好遇到领导交代一个任务,把某某网站的某某文件给复制下来,保存归档。心下甚喜,学成归来终有用武之地了,于是心急火燎的把活儿揽下来,并对领导夸口,分分钟搞定!

其实爬网站这种事情,古已有之,想当年Flashget(网际快车)和NetAnts(网络蚂蚁)风行的时候,似曾有段时间也支持过所谓的“离线网站”,一直到后来的WebZip、HTTrack,实际上都不能称为十分好用,最容易出现的问题就是该爬的没爬到,不该爬的爬了一堆,也许是我不会用的缘故吧。总之,我就是想利用所学,自己写一个工具。

有了历史经验,咱们要做的第一件事就是,声明一个路径列表,凡是从网页中解析出来的URL,又包含在该路径列表中的,一律往下爬,不要跟我扯什么最大层级,不care,因为太死板,该爬的没爬到,不该爬的爬一堆,就是这货的锅。第二件事情,因为我是用 Beautifulsoup 解析网页并分析页面内包含的URL的,所以得声明一个元素标签匹配规则列表,凡是符合匹配规则的元素,就解析其中包含的 URL放入待爬取URL列表中,这样,遇到不同的网站,只要灵活配置匹配规则即可。

自信满满的以为这样就够了,爬取库(requests)、解析库(Beautifulsoup)、待爬取URL列表、已爬取URL列表、爬取路径控制列表、爬取元素匹配规则列表,还有什么能比这更完美的吗?

事实上,我错了,原本吹嘘为分分钟的事情,最后变成了钟钟钟。。。

来看看我栽了哪些坑吧。。。

1、网页乱码

还能有比网页乱码更常见的坑吗?

我曾经特么天真的以为在使用 requests 时,设置一句 res.encoding = 'utf-8' ,就能得到完美的 utf-8 编码的字符串了呢,事实上我用print 打印出来的网页内容,也的确是正常显示的,可是一旦保存到文件,中文就成了乱码,究竟是什么鬼在捣乱???

费了半天劲,研究了各种字符串转码以及设置写文件时编码格式的办法,总算搞清楚了,原来 python3 默认是 unicode 编码(这里容我插句嘴,实际上我知道 unicode 是一种字符集而不是一种编码格式,甚至 utf-8 只是 unicode 字符集的一种编码格式而已,大家习惯称之为 unicode 编码的编码格式准确的应该称之为 usc2 ,但是谁 care 呢),而保存网页文件时,应该根据网页头部的 charset 而定,例如我们要把 utf-8 格式的网页保存到文件,大概应该要这样子:

f = open(fullname, 'wb')                 # 用二进制方式打开文件

f.write(content.encode('UTF-8'))   # 把要写入的字符串转化为相应的编码

2、网页上看到的元素结构和网页源码里的结构不同

如果我不说出来,这个谜恐怕一辈子无解了,说出来,希望有人能教我。。。

我不知道为什么会是这样子的,我在 chrome里看到的网页元素结构是这样子滴:


可以看到 table 标签下级有个 tbody 标签,可是我把标签匹配规则写成 '.page tbody tr td a' ,死活匹配不到,我反反复复一级一级缩减标签,打印内容,居然惊讶的发现,代码其实是这样子的:


也不知道为何,代码里, table 标签下没有 tbody 标签,直接就到了 tr ,我滴个神,坑爹也不是这种坑法吧,这是什么鬼???

3、css、js等文件都要抓取

一个真正的离线网站工具,并不像我想象中的那样简单,毕竟我们不是在做数据爬虫(除了‘窃取’别人的关键数据外,其他都不 care),我们想要的是一个能够在本地完美呈现的离线网站,所以 css文件、js 文件以及各种图片资源,都要爬取,有意思的是,这些乱七八糟的文件所存放的路径往往千奇百怪,这就意味着要增加我们配置爬取路径控制列表的复杂度,我想,我开始有点理解为什么离线网站工具都用一个简单的层级来控制爬取范围了。。。

忙活了半天,总算还有迹可循,但不排除有些手潮的疯子开发的不可理喻的网站。。。

4、保存图片文件

好吧,再来说说文件保存吧,如果你采用了我在坑1中建议的保存文件的方法,哈哈,恭喜你,你可能已经掉进这个坑了。

如果没有,那么恭喜你!。。。好吧,我还是承认我弄的太久了,已经开始头晕了的事实吧。

实际上保存网页文件时,需要根据字符集来灵活设置,但保存图片资源时,就不要做转码了,用二进制打开文件直接保存 content 即可,例如这样:

import requests

res = requests.get('图片url')

f = open('C:\\web\\photo.jpg', 'wb')

f.write(res.content) # 注意,这里不是 text 了,而是 content

f.close()

哦,对了,顺便说一句,我到现在还没弄清保存 css 和 js 需不需要转码保存,我想如果有中文的话,大概也需要吧,反正我是转了,没出错。

5、不认相对路径

历尽千辛万苦,从一个个坑里爬了上来,却没想,你以为的不一定是你以为的(某东广告语)。。。

我以为什么都爬下来了,相关所需的 css、js、image 一切齐整,当我打开网页时,即可欣赏自己完美的劳动成果了,结果却出人意料的恶心,神马玩意,样式全丢,图片全窟窿。。。心中顿时万马奔腾。。。

用chrome打开调试,看到控制台上一片血红的 Failed to load resource: net::ERR_FILE_NOT_FOUND ,神呐,这是为什么,为什么要如此残酷的对待我。。。

几经检查,找到了原因,原来是 MMP 的 windows 系统不能准确识别链接中的相对路径,比如:

img src="/web/images/next.gif"   (原谅我没有加尖括号,不知道为什么,加了尖括号在简书就显示不正常了

本地网页文件是没办法找到这个文件的,假设我们的 html 文件路径为 C:\offline\project1\web\html\index.html ,那么说明这个 next.gif 则存放在 html 文件的上一级目录(即web目录)下的 images 目录下,所以,这个 url 应该是这样子才能正常工作:

img src="./../../web/images/next.gif"

又或者:

img src="./../images/next.gif"

别小瞧这个修改相对路径。一款离线网站工具够不够好用,主要就靠这里了,这也是我以前用过的离线工具做的唯一值得称道的地方,只可惜我自己在做时,忘得一干二净。好吧,又是一项蛋疼的工作,我就不上代码了。

6、还有更多更深的坑在等你

非常幸运的,领导交代的任务对象只是一个简单的静态网站,而且没有做任何反爬措施,相信我,相比起动态网站,你更不想看到的是反爬的网站。。。至于怎么脱坑,抱歉,我目前还无法自救,更无论救人了。

最后

磕磕巴巴、跌跌撞撞的终于把领导需要的网站爬下来了,而实际上手动保存只需要半个钟头就够了,就在我踌躇满志的把整个离线网站打包发给领导时,领导淡淡的说了一句:“把它们做成一个pdf文件发给我。”,蛋碎。。。又一个悲伤的故事开始了。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,650评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,050评论 25 707
  • 惊蛰一过,春寒加剧。先是料料峭峭,继而雨季开始,时而淋淋漓漓,时而淅淅沥沥,天潮潮地湿湿,即连在梦里,也似乎有把...
    王三废July22th阅读 533评论 0 14
  • 你想坚持每天做的事情是? 读书,最开始从《好好学习》读起,会让自己读书的节奏慢下来,有充分的时间进行思考,保证每天...
    _尔东陈_阅读 596评论 0 1
  • 好久没玩游戏了,可能是因为时间紧压力大,又可能是因为阅历无数而失去兴趣。不过仔细一想,又好像一直在玩游戏,包括编程...
    子衿沃若阅读 135评论 0 0