小喵的唠叨话:这次的博客,讲的是使用python编写一个爬虫工具。为什么要写这个爬虫呢?原因是小喵在看完《极黑的布伦希尔特》这个动画之后,又想看看漫画,结果发现各大APP都没有资源,最终好不容易找到一个网站可以看,但是由于网速太渣,看起来额外的费劲。这时候如果能提前下载下来就好了。

先上项目地址(github):https://github.com/miaoerduo/cartoon-cat 。欢迎大家随时forkstar和指教。

原因就是这样,作为技术喵,任何问题都不能阻碍一颗爱漫画的心。所以问题就来了,挖掘机技修哪家强?

在bing上搜索Python、爬虫框架。找到大家常用的框架。

Scrapy似乎是个很不错的选择。至于相对于其他框架的优点,小喵没有细查,至少这个框架是之前听过的。但是在实现的时候发现有一些问题,scrapy不能直接抓取动态的页面。小喵需要抓取的网站的漫画都是使用Ajax生成的。需要自己分析各种数据,这个有点麻烦。

那么有没有可以渲染页面的工具呢?像浏览器一样的?有。

这里介绍两个工具:

PhantomJs,可以理解是一个浏览器。不过它没有界面,我们可以通过js的代码模拟用户的行为。这就要求了解它的api并有js基础了。

Selenium,这是个浏览器自动化测试框架。它依赖于浏览器(这个浏览器也可以是PhantomJs),通过Selenium可以模拟用户的行为。而且有Python接口,所以相对简单一些。

我们这个爬虫使用selenium + phantomjs来实现。

哟,这个爬虫软件应该有个响当当的名字。。。就叫漫画喵吧,英文名Cartoon Cat

下面我们一点点的介绍这个爬虫的实现过程吧。

一、初生-环境搭建

小喵这里选用Python作为开发语言,框架是selenium。原因是python经常用来写爬虫,selenium可以用来模拟用户行为,PhantomJs是可选的,不过小喵最终会在一个服务器上运行,所以也是需要的。

为了不影响本机上的python,我们还需要使用virtualenv来创建一个独立的python环境。具体步骤如下:

1、安装virtualenv

virtualenv是一个常用的用来创建python环境的工具。小喵用这个有两个原因,一是为了不污染本机的环境,二是在本机直接安装库的时候出了一个权限的问题。

virtualenv的安装十分简单,使用pip工具就可以安装。

1

pip install virtualenv

待程序执行结束,你就会开心的发现自己已经有了virtualenv这个工具了。

2、创建python环境

virtualenv的使用非常的方便。

建立新的运行环境:virtualenv <env-name>

进入相应的独立环境:source <env-path>/bin/activate

执行完第一个指令后,就会创建成功一个python环境,执行第二个指令后,就会发现命令行的起始位置有变化。这时候python、pip等工具就变成使用这个新环境的了,当然也可以使用which python来查看。

3、安装selenium

进入新环境后,pip安装的依赖库都会在新环境中安装,不会影响主机自身的python。使用pip 安装selenium:

1

pip install selenium

至此,我们的基本环境就搭建完了。

4、安装PhantomJs

这个只在从官网上下载就可以:http://phantomjs.org/download.html

小喵的本地实验环境是Mac,所以下载了Mac版本。解压之后就可以使用。

二、寻觅-搜资源

小喵想看的这个漫画貌似各大网站都没有资源,在费了九牛二虎之力后,终于找到了一个网站!http://www.tazhe.com/mh/9170/。

每个网站的结构都不相同,因此都需要定制一套爬虫程序。本文的爬虫就只能针对这个漫画网站使用,喵粉们需要爬其他网站的话,需要自己做相应的修改。

三、分析-资源解析

这里需要解析两个页面,一个是漫画的首页,比如前面的:http://www.tazhe.com/mh/9170/

另一个就是具体章节的页面。

1,首页

为了减小图片的大小,小喵把窗口做了缩放。首页大致是这个样子。

图1 漫画首页

各类信息十分的明了。我们关注的就是下面的漫画列表。通过Chrome强大的审查元素的功能,我们立刻就能定位到章节的位置。(对着感兴趣的位置->右键->审查 就能找到)

图2 章节的节点

可以看到,章节所在的区域的idplay_0,学过前端的童鞋都应该知道,一个页面中id通常唯一标示一个节点。因此如果我们能够获取这个页面的话,查找idplay_0的节点就能一下子缩小搜索范围。

而每个章节的信息都是一个a标签,标签的href是对应章节的具体网址,标签的文本部分是章节名。这样相对关系就得出了:div#play_0 > ul > li > a

首页的分析就到此结束。

2、章节页面

我们随意打开一个具体章节的页面。比如:http://www.tazhe.com/mh/9170/1187086.html

引入眼帘的是一个很干净的页面(简直是漫画界的清流,好多漫画网站上全部是广告)。

我们把鼠标放在图片这个区域->右键->审查

咦,我们的右键怎么按不了?

其实呢,这个现象在小说网站上遇到的机会会更多。当我们看到比较优美的文字或是炫酷的图片,都会下意识的选中->右键->保存。而很多时候,这些资源都是有版权的。并不应该随意的传播(狠狠的打了自己的脸/(ㄒoㄒ)/~~)。因此限制鼠标右键会是一个很简单却有效的办法。

那么我们如何绕过这个陷阱呢?

很简单,我们不用右键即可。打开浏览器的开发者工具选项,找到elements这个选项。可以看到一个复杂的结构(其实和上面审查元素之后的结果一样)。之后不断的选中标签,当标签被选中时,左侧页面中对应的位置会有蓝色。多试几次,最终就能找到对应的位置。

图3 漫画图片

这是一个img标签,对应的idqTcms_pic。这样找到这个id,就能找到这个img标签,根据src就能找到图片的具体URI地址。

接下来是找到下一张图片的地址。这时候需要查看下一页这个按钮的内容。用相同的方法,很容易定位成功。

图4 下一页

小喵本来是用scrapy来做爬虫的,看到这里的时候就果断放弃了。我们分析一下,选中的a标签的代码如下:

1

<a class="next" href="javascript:a_f_qTcms_Pic_nextUrl_Href();" title="下一页"><span>下一页</span></a>

比较简单的网站,“下一页”可以用真的a标签和href属性来做。这样的好处是实现比较简单,坏处是一旦得到网页源码就能很容易的解析。而像scrapy这样的爬虫工具只能抓取静态的代码(动态的需要自己分析ajax,有点麻烦)。而显然这里的页面是动态的,使用了ajax来实现。所以光是得到网页源码并不能真的得到图片,而是必须让其中的js代码运行才可以。所以我们才需要使用浏览器或者PhantomJs这样的可以执行js代码的工具。

上面的a标签的代码告诉了我们很多信息。首先是告诉了我们,这个节点的位置,通过next这个类名可以方便的找到该节点(其实有两个类名为next的按钮,另一个在下面,但是功能都一样)。其次,当这个按钮被点击时会调用:a_f_qTcms_Pic_nextUrl_Href()这个js函数。难道我们需要再研究这个函数?

不用。因为PhantomJs的角色就是一个浏览器。我们只需要向真正的用户一样点击一下这个next按钮,就会进入下一个页面。/* 感受到这个工具的强大了吗? */

3、判断章节的末尾

最后一个问题就是,如何判断这个章节结束了?

我们跳到章节的最后一页,然后再次点击“下一页”,这时候会出现一个弹窗。

图5 最后一页

多次试验之后,我们会发现,只有在最后一页的时候才会弹出这个弹窗,这样的话,我们每抓取完一页,点击一次“下一页”,判断有无弹窗就知道是不是最后一页了。在右侧的开发者工具中我们能够看到,这个弹窗是一个idmsgDivdiv(而且它的出现和消失是通过增减节点来实现的,另一种实现方法是将display设成noneblock,这种情况可以根据display的属性来判断)。所以我们判断这个节点存不存在就行了。

至此,两种页面的解析都完成了。下一步就开始我们的代码实现吧。

四、逆袭——代码实现

1,selenium的简单用法

1

2

3

4

5

6

7

8

9

10

11

12

from selenium import webdriver

browser = webdriver.Firefox()

# browser = webdriver.Safari()

# browser = webdriver.Chrome()

# browser = webdriver.Ie()

# browser = webdriver.PhantomJs()

browser.get('http://baidu.com')

print browser.title

# do anything you want

上面是一个简单的例子,第一步import依赖的库。

第二步,获得一个浏览器实例。selenium支持多种浏览器。使用firefox之外的浏览器都需要下载驱动(selenium本身自带了firefox的驱动)。驱动下载地址:https://pypi.python.org/pypi/selenium 。驱动下载完之后将它的路径加入到PATH里,确保驱动程序能够被访问到。或者显式的把驱动程序的地址当参数传入。像下面一样调用:

1

browser = webdriver.PhantomJs('path/to/phantomjs')

第三步,用get的方式打开网页。

最后,通过browser对象来解析和处理页面。

2,获取章节的链接信息

在上面的解析页面的时候,我们知道了章节信息的位置:div#play_0 > ul > li > a。这样就可以解析出章节信息。browser支持一大堆的选择器。大大简化我们查找节点的工作。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

from selenium import webdriver

if __name__ == "__main__":

driver = "path/to/driver" # 驱动地址

browser = webdriver.PhantomJS(driver) # 浏览器实例

main_page = "http://www.tazhe.com/mh/9170/"

browser.get(main_page) # 加载页面

# 解析出章节的元素节点

chapter_elem_list = browser.find_elements_by_css_selector('#play_0 ul li a') # 通过css选择器找出章节节点

chapter_elem_list.reverse()  # 原本的章节是倒叙的

chapter_list = []

for chapter_elem in chapter_elem_list:

# 元素的text和href属性分别就是章节的名称和地址

chapter_list.append((chapter_elem.text, chapter_elem.get_attribute('href')))

# chapter_list 就是章节的信息

3,给定一个章节的地址,章节中的图片

这一步涉及到节点的获取、模拟鼠标的点击以及资源的下载。selenium的点击实现特别的人性化。只需要获取节点然后调用click()方法就搞定。资源的下载网上有许多教程,主要有两个方法,通过模拟右键另存为,和获取url用其他工具下载。考虑到这里的右键不一定可用,而且操作有一点点复杂。小喵选用了第二种方案。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

from selenium import webdriver

from selenium.common.exceptions import NoSuchElementException

import os

from os import path as osp

import urllib

# 一个简单的下载器

download(url, save_path):

try:

with open(save_path, 'wb') as fp:

fp.write(urllib.urlopen(url).read())

except Exception, et:

print(et)

if __name__ == "__main__":

driver = "path/to/driver" # 驱动地址

browser = webdriver.PhantomJS(driver) # 浏览器实例

chapter_url = "http://www.tazhe.com/mh/9170/1187061.html"

save_folder = "./download"

if not osp.exists(save_folder):

os.mkdir(save_folder)

image_idx = 1

browser.get(chapter_url) # 加载第一个页面

while True:

# 根据前文的分析,找到图片的URI地址

image_url = browser.find_element_by_css_selector('#qTcms_pic').get_attribute('src')

save_image_name = osp.join(save_folder, ('%05d' % image_idx) + '.' + osp.basename(image_url).split('.')[-1])

download(image_url, save_image_name) # 下载图片

# 通过模拟点击加载下一页,注意如果是最后一页,会出现弹窗提示

browser.find_element_by_css_selector('a.next').click()

try:

# 找寻弹窗,如果弹窗存在,说明这个章节下载完毕,这个大循环也就结束了

browser.find_element_by_css_selector('#bgDiv')

break

except NoSuchElementException:

# 没有结束弹窗,继续下载

image_idx += 1

五、终焉-写在后面

至此,漫画喵的设计思路和主要的代码实现都介绍完了。上面的代码只是用来示意,小喵自己下载漫画用的代码是另一套。github的地址是:https://github.com/miaoerduo/cartoon-cat 。项目只有100多行。不过也用了小喵不少的一段时间。

博客写完了~小喵的漫画也下完了~

图6 下载好的漫画

转载于:https://www.cnblogs.com/paisenpython/p/10323255.html

一百行代码爬取漫画喵相关推荐

  1. pyquery获取不到网页完整源代码_爬虫神器之PyQuery实用教程(二),50行代码爬取穷游网...

    爬虫神器之PyQuery实用教程(二),50行代码爬取穷游网 前言 上篇文章 PyQuery (一) 回顾.今天来介绍具体 PyQuery 的使用方法. 穷游网目标与分析 开始之前,按照之前的套路一步 ...

  2. Python爬虫利用18行代码爬取虎牙上百张小姐姐图片

    Python爬虫利用18行代码爬取虎牙上百张小姐姐图片 下面开始上代码 需要用到的库 import request #页面请求 import time #用于时间延迟 import re #正则表达式 ...

  3. python爬上市公司信息_实战项目 1:5 行代码爬取国内所有上市公司信息

    实战项目 1:5 行代码爬取国内所有上市公司信息 Python入门爬虫与数据分析 在正式开始这门专栏课的学习之前,我们先来看一个简单的爬虫案例.兴趣是最好的老师,当你对爬虫产生兴趣的时候,才会更有动力 ...

  4. 简单20行代码爬取王者荣耀官网1080p壁纸

    简单20行代码爬取王者荣耀官网1080p壁纸 # -*- coding: utf-8 -*- # @Time : 2020/12/13 18:08 # @Author : ningfangcong i ...

  5. Python25行代码爬取豆瓣排行榜数据

    Python25行代码爬取豆瓣排行榜数据 只需要用到requests, re ,csv 三个库即可. code import re import requests import csv url = ' ...

  6. python:利用20行代码爬取网络小说

    文章目录 前言 一.爬虫是什么? 二.实现过程 总结 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 今天,来给大家一个分享一下如何使用20爬虫行代码爬取网络小说(这里我们以龙 ...

  7. python59行代码爬取免费ppt模板

    Python59行代码爬取某站中秋节ppt模板 网址:https://www.1ppt.com/moban/zhongqiujie/ 用到的库:requests.re.os.lxml 请求方式:GET ...

  8. 教你用python实现34行代码爬取东方财富网信息,爬虫之路,永无止境!!

    教你用python实现34行代码爬取东方财富网信息,爬虫之路,永无止境!! 代码展示: 开发环境: windows10 python3.6 开发工具: pycharm weddriver 库: sel ...

  9. python pyquery不规则数据的抓取_爬虫神器之PyQuery实用教程(二),50行代码爬取穷游网...

    爬虫神器之PyQuery实用教程(二),50行代码爬取穷游网 前言 上篇文章 PyQuery (一) 回顾.今天来介绍具体 PyQuery 的使用方法. 穷游网目标与分析 开始之前,按照之前的套路一步 ...

最新文章

  1. ugly number
  2. excel 多列匹配相等后 引用值
  3. 忙了一上午终于把形状特征搞定了啊
  4. 运维小姐姐说这篇Consul集群和ACL配置超给力(保姆级)
  5. 戴明博士:管理的十四项原则
  6. 非接触式IC智能(射频)卡
  7. Java关键字(六)——super
  8. 2019 年编写现代 JavaScript 代码的5个小技巧
  9. python calu()函数_酚酞指示剂是一类什么物质,它在PH=10时是什么颜色呢(     )...
  10. 百度地图坐标和高德地图坐标转换
  11. IE11降级到IE8
  12. 模拟电子技术基础(一)
  13. php实现根据身份证获取年龄的函数
  14. Python pandas库的简单使用
  15. MyEclipse 下载、安装教程
  16. r矢量球坐标系旋度_球面,柱面坐标系下的散度与旋度
  17. 动态内存的开辟与释放
  18. 中国工程院院士、中国人工智能学会理事长李德毅:人工智能研究新进展
  19. GNSS说第(七)讲---自适应动态导航定位(六)---导航解算中的误差探测、诊断与修复
  20. HTML,css和JavaScript的基础学习—html篇

热门文章

  1. 分布式缓存 - memCached Voldemort
  2. 《考研公共课复习指导》随笔及其它
  3. backtrader概念(二)Trade
  4. 2021爱彼迎年度民宿榜单出炉,住进全国100家优质乡野民宿
  5. 站内信 java_站内信的实现思路表的设计
  6. 小白成长之路_今天学到的(2018.4.16)
  7. 移动应用、大数据等推动广域网优化未来三年高速增长
  8. <video> 标签快进不生效
  9. 阿里开源的这个库,让 Excel 导出不再复杂(既要能写,还要写的好看)
  10. hapi_带有节点和Hapi后端的Angular文件上传