天天看点

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

<a target="_blank" href="http://www.pyspider.cn/book/pyspider/pyspider-quickstart-2.html">pyspider 中文文档</a>

1. 抓取、更新调度多站点的特定的页面

2. 需要对页面进行结构化信息提取

3. 灵活可扩展,稳定可监控

而这也是绝大多数python爬虫的需求 —— 定向抓取,结构化化解析。但是面对结构迥异的各种网站,单一的抓取模式并不一定能满足,灵活的抓取控制是必须的。为了达到这个目的,单纯的配置文件往往不够灵活,于是,通过脚本去控制抓取是最后的选择。

而去重调度,队列,抓取,异常处理,监控等功能作为框架,提供给抓取脚本,并保证灵活性。最后加上web的编辑调试环境,以及web任务监控,即成为了这套框架。

pyspider的设计基础是:以python脚本驱动的抓取环模型爬虫

1. 通过python脚本进行结构化信息的提取,follow链接调度抓取控制,实现最大的灵活性

2. 通过web化的脚本编写、调试环境。web展现调度状态

3. 抓取环模型成熟稳定,模块间相互独立,通过消息队列连接,从单进程到多机分布式灵活拓展

pyspider的架构主要分为 scheduler(调度器), fetcher(抓取器), processor(脚本执行):

1. 各个组件间使用消息队列连接,除了scheduler是单点的,fetcher 和 processor 都是可以多实例分布式部署的。 scheduler 负责整体的调度控制

2. 任务由 scheduler 发起调度,fetcher 抓取网页内容, processor 执行预先编写的python脚本,输出结果或产生新的提链任务(发往 scheduler),形成闭环。

3. 每个脚本可以灵活使用各种python库对页面进行解析,使用框架api控制下一步抓取动作,通过设置回调控制解析动作。

爬虫pyspider提供一个异常强大的网页界面(web ui),它允许你编辑和调试你的脚本,管理整个抓取过程,监控正在进行的任务,并最终输出结果。

项目和任务

代码结构分析

根目录:在根目录中可以找到的文件夹有:

这里重点介绍一些重要的文件:

分析完项目的根目录了,仅根目录就能说明该项目是以一种非常专业的方式进行开发的。如果你正在开发任何的开源程序,希望你能达到这样的水准。

文件夹pyspider

文件run.py

函数cli()

函数all()

函数all()决定是否运行子进程或者线程,然后调用不同的线程或子进程里的所有的必要函数。这时pyspider将产生包括webui在内的,爬虫的所有逻辑模块所需要的,足够数量的线程。当我们完成项目并关闭webui时,我们将干净漂亮地关闭每一个进程。

现在我们的爬虫就开始运行了,让我们进行更深入一点儿的探索。

调度程序

调度程序从两个不同的队列中获取任务(newtask_queue和status_queue),并把任务加入到另外一个队列(out_queue),这个队列稍后会被抓取程序读取。

调度程序做的第一件事情是从数据库中加载所需要完成的所有的任务。之后,它开始一个无限循环。在这个循环中会调用几个方法:

循环也会检查运行过程中的异常,或者我们是否要求python停止处理。

抓取程序

抓取程序的目的是检索网络资源。

pyspider能够处理普通html文本页面和基于ajax的页面。只有抓取程序能意识到这种差异,了解这一点非常重要。我们将仅专注于普通的html文本抓取,然而大部分的想法可以很容易地移植到ajax抓取器。

这里的想法在某种形式上类似于调度程序,我们有分别用于输入和输出的两个队列,以及一个大的循环。对于输入队列中的所有元素,抓取程序生成一个请求,并将结果放入输出队列中。

它听起来简单但有一个大问题。网络通常是极其缓慢的,如果因为等待一个网页而阻止了所有的计算,那么整个过程将会运行的极其缓慢。解决方法非常的简单,即不要在等待网络的时候阻塞所有的计算。这个想法即在网络上发送大量消息,并且相当一部分消息是同时发送的,然后异步等待响应的返回。一旦我们收回一个响应,我们将会调用另外的回调函数,回调函数将会以最适合的方式管理这样的响应。

现在我们的脑海里已经有了极好的想法了,让我们更深入地探索这是如何实现的。

函数run()是抓取程序fetcher中的一个大的循环程序。

函数run()中定义了另外一个函数queue_loop(),该函数接收输入队列中的所有任务,并抓取它们。同时该函数也监听中断信号。函数queue_loop()作为参数传递给tornado的类periodiccallback,如你所猜,periodiccallback会每隔一段具体的时间调用一次queue_loop()函数。函数queue_loop()也会调用另一个能使我们更接近于实际检索web资源操作的函数:fetch()。

函数fetch(self, task, callback=none)

网络上的资源必须使用函数phantomjs_fetch()或简单的http_fetch()函数检索,函数fetch()只决定检索该资源的正确方法是什么。接下来我们看一下函数http_fetch()。

函数http_fetch(self, url, task, callback)

终于,这里才是完成真正工作的地方。这个函数的代码有点长,但有清晰的结构,容易阅读。

在函数的开始部分,它设置了抓取请求的header,比如user-agent、超时timeout等等。然后定义一个处理响应response的函数:handle_response(),后边我们会分析这个函数。最后我们得到一个tornado的请求对象request,并发送这个请求对象。请注意在异步和非异步的情况下,是如何使用相同的函数来处理响应response的。

让我们往回看一下,分析一下函数handle_response()做了什么。

函数handle_response(response)

这个函数以字典的形式保存一个response的所有相关信息,例如url,状态码和实际响应等,然后调用回调函数。这里的回调函数是一个小方法:send_result()。

函数send_result(self, type, task, result)

这个最后的函数将结果放入到输出队列中,等待内容处理程序processor的读取。

内容处理程序processor

内容处理程序的目的是分析已经抓取回来的页面。它的过程同样也是一个大循环,但输出中有三个队列(status_queue, newtask_queue 以及result_queue)而输入中只有一个队列(inqueue)。

让我们稍微深入地分析一下函数run()中的循环过程。

函数run(self)

这个函数的代码比较少,易于理解,它简单地从队列中得到需要被分析的下一个任务,并利用on_task(task, response)函数对其进行分析。这个循环监听中断信号,只要我们给python发送这样的信号,这个循环就会终止。最后这个循环统计它引发的异常的数量,异常数量过多会终止这个循环。

函数on_task(self, task, response)

函数on_task()是真正干活的方法。

它尝试利用输入的任务找到任务所属的项目。然后它运行项目中的定制脚本。最后它分析定制脚本返回的响应response。如果一切顺利,将会创建一个包含所有我们从网页上得到的信息的字典。最后将字典放到队列status_queue中,稍后它会被调度程序重新使用。

如果在分析的页面中有一些新的链接需要处理,新链接会被放入到队列newtask_queue中,并在稍后被调度程序使用。

现在,如果有需要的话,pyspider会将结果发送给其他项目。

最后如果发生了一些错误,像页面返回错误,错误信息会被添加到日志中。

scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。

其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取api所返回的数据(例如 amazon associates web services

) 或者通用的网络爬虫。scrapy用途广泛,可以用于数据挖掘、监测和自动化测试

scrapy 使用了 twisted 异步网络库来处理网络通讯。整体架构大致如下

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

scrapy主要包括了以下组件:

1. 引擎(scrapy): 用来处理整个系统的数据流处理, 触发事务(框架核心)

2. 调度器(scheduler): 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个url(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址

3. 下载器(downloader): 用于下载网页内容, 并将网页内容返回给蜘蛛(scrapy下载器是建立在twisted这个高效的异步模型上的)

4. 爬虫(spiders): 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(item)。用户也可以从中提取出链接,让scrapy继续抓取下一个页面

5. 项目管道(pipeline): 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

6. 下载器中间件(downloader middlewares): 位于scrapy引擎和下载器之间的框架,主要是处理scrapy引擎与下载器之间的请求及响应。

7. 爬虫中间件(spider middlewares): 介于scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。

8. 调度中间件(scheduler middewares): 介于scrapy引擎和调度之间的中间件,从scrapy引擎发送到调度的请求和响应。

scrapy运行流程大概如下:

1. 首先,引擎从调度器中取出一个链接(url)用于接下来的抓取

2. 引擎把url封装成一个请求(request)传给下载器,下载器把资源下载下来,并封装成应答包(response)

3. 然后,爬虫解析response

4. 若是解析出实体(item),则交给实体管道进行进一步的处理。

5. 若是解析出的是链接(url),则把url交给scheduler等待抓取

1. pip。首先确保你已经安装了pip,若没有安装,请参照

<a target="_blank" href="http://pip-cn.readthedocs.io/en/latest/installing.html">pip安装</a>

3. pyspider。直接利用 pip 安装即可:pip install pyspider。如果你是 ubuntu 用户,请提前安装好以下支持类库

4. 测试。如果安装过程没有提示任何错误,那就证明一些ok。命令行输入:pyspider all (这句命令的意思是,运行 pyspider 并 启动它的所有组件。)。然后浏览器访问 http://localhost:5000 观察一下效果,如果可以正常出现 pyspider 的页面,那证明一切ok,在此附图一张,这是我写了几个爬虫之后的界面。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

接下来我会进一步介绍这个框架的使用。

pyspider 是一个非常方便并且功能强大的爬虫框架,支持多线程爬取、js动态解析,提供了可操作界面、出错重试、定时爬取等等的功能,使用非常人性化。

爬取目标网站:https://mm.taobao.com/json/request_top_list.htm?page=1,大家打开之后可以看到许多淘宝mm的列表。

列表有多少?

https://mm.taobao.com/json/request_top_list.htm?page=10000,第10000页都有,看你想要多少。我什么也不知道。

随机点击一位 mm 的姓名,可以看到她的基本资料。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

可以看到图中有一个个性域名,我们复制到浏览器打开。mm.taobao.com/tyy6160

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

嗯,往下拖,海量的 mm 图片都在这里了,怎么办你懂得,我们要把她们的照片和个人信息都存下来。

p.s. 注意图中进度条!你猜有多少图片~

安装成功之后,跟我一步步地完成一个网站的抓取,你就会明白 pyspider 的基本用法了。

命令行下执行:pyspider all。这句命令的意思是,运行 pyspider 并 启动它的所有组件。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

可以发现程序已经正常启动,并在 5000 这个端口运行。接下来在浏览器中输入 http://localhost:5000,可以看到 pyspider 的主界面,点击右下角的 create,命名为 taobaomm,当然名称你可以随意取,继续点击 create。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

这样我们会进入到一个爬取操作的页面。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

整个页面分为两栏,左边是爬取页面预览区域,右边是代码编写区域。下面对区块进行说明:

左侧绿色区域:这个请求对应的 json 变量,在 pyspider 中,其实每个请求都有与之对应的 json 变量,包括回调函数,方法名,请求链接,请求数据等等。

绿色区域右上角run:点击右上角的 run 按钮,就会执行这个请求,可以在左边的白色区域出现请求的结果。

左侧 enable css selector helper: 抓取页面之后,点击此按钮,可以方便地获取页面中某个元素的 css 选择器。

左侧 web: 即抓取的页面的实时预览图。

左侧 html: 抓取页面的 html 代码。

左侧 follows: 如果当前抓取方法中又新建了爬取请求,那么接下来的请求就会出现在 follows 里。

左侧 messages: 爬取过程中输出的一些信息。

右侧代码区域: 你可以在右侧区域书写代码,并点击右上角的 save 按钮保存。

右侧 webdav mode: 打开调试模式,左侧最大化,便于观察调试。

依然是上面那个网址,https://mm.taobao.com/json/request_top_list.htm?page=1,其中 page 参数代表页码。所以我们暂时抓取前 30 页。页码到最后可以随意调整。

首先我们定义基地址,然后定义爬取的页码和总页码。

点击 save 保存代码,然后点击左边的 run,运行代码。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

运行后我们会发现 follows 出现了 30 这个数字,说明我们接下来有 30 个新请求,点击可查看所有爬取列表。另外控制台也有输出,将所有要爬取的 url 打印了出来。

然后我们点击左侧任意一个绿色箭头,可以继续爬取这个页面。例如点击第一个 url,来爬取这个 url

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

点击之后,再查看下方的 web 页面,可以预览实时页面,这个页面被我们爬取了下来,并且回调到 index_page 函数来处理,目前 index_page 函数我们还没有处理,所以是继续构件了所有的链接请求。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

好,接下来我们怎么办?当然是进入到 mm 到个人页面去爬取了。

爬取到了 mm 的列表,接下来就要进入到 mm 详情页了,修改 index_page 方法。

其中 response 就是刚才爬取的列表页,response 其实就相当于列表页的 html 代码,利用 doc 函数,其实是调用了 pyquery,用 css 选择器得到每一个mm的链接,然后重新发起新的请求。比如,我们这里拿到的 each.attr.href 可能是 mm.taobao.com/self/model_card.htm?user_id=687471686,在这里继续调用了 crawl 方法,代表继续抓取这个链接的详情。

然后回调函数就是 detail_page,爬取的结果会作为 response 变量传过去。detail_page 接到这个变量继续下面的分析。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

好,我们继续点击 run 按钮,开始下一个页面的爬取。得到的结果是这样的。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

哦,有些页面没有加载出来,这是为什么?在之前的文章说过,这个页面比较特殊,右边的页面使用 js 渲染生成的,而普通的抓取是不能得到 js 渲染后的页面的,这可麻烦了。然而,幸运的是,pyspider 提供了动态解析 js 的机制。

如果已经装好了 phantomjs,这时候就轮到它来出场了。在最开始运行 pyspider 的时候,使用了pyspider all命令,这个命令是把 pyspider 所有的组件启动起来,其中也包括 phantomjs。

所以我们代码怎么改呢?很简单。

只是简单地加了一个 fetch_type=’js’,点击绿色的返回箭头,重新运行一下。可以发现,页面已经被我们成功加载出来了,简直不能更帅!

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

看下面的个性域名,所有我们需要的 mm 图片都在那里面了,所以我们需要继续抓取这个页面。

好,继续修改 detail_page 方法,然后增加一个 domain_page 方法,用来处理每个 mm 的个性域名。

好,继续重新 run,预览一下页面,终于,我们看到了 mm 的所有图片。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

照片都有了,那么我们就偷偷地下载下来吧~。完善 domain_page 代码,实现保存简介和遍历保存图片的方法。

在这里,pyspider 有一个特点,所有的 request 都会保存到一个队列中,并具有去重和自动重试机制。所以,我们最好的解决方法是,把每张图片的请求都写成一个 request,然后成功后用文件写入即可,这样会避免图片加载不全的问题。

曾经在之前文章写过图片下载和文件夹创建的过程,在这里就不多赘述原理了,直接上写好的工具类,后面会有完整代码。

这里面包含了四个方法。

然后在 domain_page 中具体实现如下

以上方法首先获取了页面的所有文字,然后调用了 savebrief 方法存储简介。

然后遍历了 mm 所有的图片,并通过链接获取后缀名,和 mm 的姓名以及自增计数组合成一个新的文件名,调用 saveimg 方法保存图片。

基本的东西都写好了。接下来。继续完善一下代码。第一版本完成。

版本一功能:按照淘宝mm姓名分文件夹,存储mm的 txt 文本简介以及所有美图至本地。

可配置项:

粘贴到你的 pyspider 中运行吧~。其中有一些知识点,我会在后面作详细的用法总结。大家可以先体会一下代码。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

保存之后,点击下方的 run,你会发现,海量的 mm 图片已经涌入你的电脑啦~

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践
python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

项目代码:

<a target="_blank" href="https://github.com/cqcre/taobaomm">taobaomm – github</a>

开始之前

你还应该至少对万维网是什么有一个简单的认识:

所以,爬网页实际上就是:

找到包含我们需要的信息的网址(url)列表

通过 http 协议把页面下载回来

从页面的 html 中解析出需要的信息

找到更多这个的 url,回到 2 继续

选取一个开始网址

既然我们要爬所有的电影,首先我们需要抓一个电影列表,一个好的列表应该:

包含足够多的电影的 url

通过翻页,可以遍历到所有的电影

一个按照更新时间排序的列表,可以更快抓到最新更新的电影

创建一个项目

在 pyspider 的 dashboard 的右下角,点击 "create" 按钮

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

替换 <code>on_start</code> 函数的 <code>self.crawl</code> 的

url:

<code>self.crawl</code> 告诉 pyspider 抓取指定页面,然后使用 <code>callback</code> 函数对结果进行解析。

点击绿色的 <code>run</code> 执行,你会看到 <code>follows</code> 上面有一个红色的

1,切换到 <code>follows</code> 面板,点击绿色的播放按钮:

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

tag 列表页

url 的方法就是用正则从中过滤出来:

由于 电影列表页和 tag列表页长的并不一样,在这里新建了一个 <code>callback</code> 为 <code>self.list_page</code>

<code>@config(age=10 * 24 * 60 * 60)</code> 在这表示我们认为

10 天内页面有效,不会再次进行更新抓取

由于 pyspider 是纯 python 环境,你可以使用 python 强大的内置库,或者你熟悉的第三方库对页面进行解析。不过更推荐使用 css选择器。

电影列表页

再次点击 <code>run</code> 让我们进入一个电影列表页(<code>list_page</code>)。在这个页面中我们需要提取:

下一页的链接,用来翻页

css选择器

css selector helper

在 pyspider 中,还内置了一个 <code>css selector helper</code>,当你点击页面上的元素的时候,可以帮你生成它的 css选择器 表达式。你可以点击 <code>enable css selector helper</code> 按钮,然后切换到 <code>web</code> 页面:

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

开启后,鼠标放在元素上,会被黄色高亮,点击后,所有拥有相同 css选择器 表达式的元素会被高亮。表达式会被插入到 python 代码当前光标位置。创建下面的代码,将光标停留在单引号中间:

点击一个电影的链接,css选择器 表达式将会插入到你的代码中,如此重复,插入翻页的链接:

翻页是一个到自己的 <code>callback</code> 回调

电影详情页

再次点击 <code>run</code>,follow

到详情页。使用 <code>css selector helper</code> 分别添加电影标题,打分和导演:

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

右键点击需要提取的元素,点击审查元素。你并不需要像自动生成的表达式那样写出所有的祖先节点,只要写出那些能区分你不需要的元素的关键节点的属性就可以了。不过这需要抓取和网页前端的经验。所以,学习抓取的最好方法就是学会这个页面/网站是怎么写的。

你也可以在 chrome dev tools 的 javascript console 中,使用 <code>$$(a[rel="v:directedby"])</code> 测试

css selector。

开始抓取

使用 <code>run</code> 单步调试你的代码,对于用一个 <code>callback</code> 最好使用多个页面类型进行测试。然后保存。

回到 dashboard,找到你的项目

将 <code>status</code> 修改为 <code>debug</code> 或 <code>running</code>

按 <code>run</code> 按钮

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

在上面教程中,用 <code>self.crawl</code> api

html 代码中。

ajax

通过使用原有的 web 标准组件,实现了在不重新加载整个页面的情况下,与服务器进行数据交互。例如在新浪微博中,你可以展开一条微博的评论,而不需要重新加载,或者打开一个新的页面。但是这些内容并不是一开始就在页面中的(这样页面就太大了),而是在你点击的时候被加载进来的。这就导致了你抓取这个页面的时候,并不能获得这些评论信息(因为你没有『展开』)。

html 更容易解析。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

你会发现电影是『载入中...』

找到真实的请求

打开一个新窗口

按 <code>ctrl</code>+<code>shift</code>+<code>i</code> (在

mac 上请按 <code>cmd</code>+<code>opt</code>+<code>i</code>)

打开开发者工具。

切换到网络( netwotk 面板)

在页面加载的过程中,你会在面板中看到所有的资源请求。

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践
python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

在豆瓣这个例子中,xhr 请求并不多,可以挨个查看来确认。但在 xhr 请求较多的时候,可能需要结合触发动作的时间,请求的路径等信息帮助在大量的请求中找到包含信息的关键请求。这需要抓取或者前端的相关经验。所以,有一个我一直在提的观点,学习抓取的最好方法是:学会写网站。

你可以使用 <code>response.json</code> 将结果转为一个 python 的 <code>dict</code> 对象

http

url 进行了抓取。这些抓取就是通过 http 协议传输的。

在抓取过程中,你可能会遇到类似 <code>403 forbidden</code>,或者需要登录的情况,这时候你就需要正确的 http 参数进行抓取了。

请求的第一行包含 <code>method</code>, <code>path</code> 和

http 协议的版本信息

余下的行被称为 header,是以 <code>key: value</code> 的形式呈现的

如果是 post 请求,在请求结尾可能还会有 <code>body</code> 内容

python爬虫框架-PySpiderPySpiderScrapy安装PySpider的用法pyspider 爬虫教程漫谈Pyspider网络爬虫的实践

在大多数时候,使用正确的 <code>method</code>, <code>path</code>, <code>headers</code> 和 <code>body</code> 总是能抓取到你需要的信息的。

http method

get 方式,而在提交数据的时候一般使用 post。

todo: need example here

http headers

headers 列表。一些常用的需要注意的有:

user-agent

ua 是标识你使用的浏览器,或抓取程序的一段字符串。pyspider 使用的默认 ua 是 <code>pyspider/version (+http://pyspider.org/)</code>。网站常用这个字符串来区分用户的操作系统和浏览器,以及判断对方是否是爬虫。所以在抓取的时候,常常会对

ua 进行伪装。

referer

referer 用于告诉服务器,你访问的上一个网页是什么。常常被用于防盗链,在抓取图片的时候可能会用到。

x-requested-with

带有 <code>headers={'x-requested-with': 'xmlhttprequest'}</code> 才能抓取到内容。

http cookie

虽然 <code>cookie</code> 只是

http header 中的一个,但是因为非常重要,但是拿出来说一下。<code>cookie</code> 被

http 请求用来区分、追踪用户的身份,当你在一个网站登录的时候,就是通过写入 <code>cookie</code> 字段来记录登录状态的。

当遇到需要登录的网站,你需要通过设置 cookie 参数,来请求需要登录的内容。cookie 可以通过开发者工具的请求面板,或者是资源面板中获得。在

pyspider 中,你也可以使用 <code>response.cookies</code> 获得返回的

cookie,并使用 <code>self.crawl(url, cookie={'key': 'value'})</code> 来设置请求的

cookie 参数。

使用 phantomjs

当 pyspider 连上 phantomjs 代理后,你就能通过在 <code>self.crawl</code> 中添加 <code>fetch_type='js'</code> 的参数,开启使用

phantomjs 直接抓取:

在页面上执行自定义脚本

20 条。当你点击『加载更多』时,能获得更多的热门电影。为了获得更多的电影,我们可以使用 <code>self.crawl</code> 的 <code>js_script</code> 参数,在页面上执行一段脚本,点击加载更多:

由于是 ajax 异步加载的,在页面加载完成时,第一页的电影可能还没有加载完,所以我们用 <code>settimeout</code> 延迟

1 秒执行。

你可以间隔一定时间,多次点击,这样可以加载更多页。

由于相同 url (实际是相同 taskid) 的任务会被去重,所以这里为 url 加了一个 <code>#more</code>

<a target="_blank" href="https://www.figotan.org/2016/08/10/pyspider-as-a-web-crawler-system/?utm_source=tuicool&amp;utm_medium=referral">转载地址</a>

为什么是python

写网络爬虫的语言有很多,编程的语言更多。个人认为python是一种工具型的语言,上手快,语法简单(相比于c/c++/java族),各种功能库丰富而且小巧单一(每个独立的库只做一件事情),所以编程就像是在玩乐高积木,照着自己设计好的流程,拼接就行了。当然,这是笔者个人的经验和喜好。如果你有自己擅长并喜欢的,大可用自己的去实现一个网络爬虫系统,这个不在本文的讨论范围之类了。

为什么是pyspider

很多推荐用requests做请求,query/soup做页面数据(html/xml)解析,看起来很灵活,然而,一个比较完善的网络爬虫系统,所需要提供的功能可能远远不止这些。也有推荐scrapy的,虽然看起来功能非常强大,但是这个框架上手需要一些时间,有一定的学习成本,相对于新手来说,很难快速专注爬虫业务的开发。

目标网站上的内容元素的解析,而且只需要关注解析什么,解析框架也有提供,并且提供了可视化工具辅助从目标页面抠取需要解析的元素css属性

解析出来的内容元素如何保存,你只需要关注数据库表字段的设计,然后把解析出来的页面元素内容保存到数据库表中

那么,剩下的几乎所有事情,就交给pyspider吧

简单的爬取看官方文档就可以了,不过,实践过程中总会遇到各种问题,那么,看看这些如何解决的吧。

如何模拟登陆

有些网站内容的展示需要用户登录,那么如果需要爬取这样的页面内容,我们的爬虫就需要模拟用户登陆。网站一般在页面跳转或者刷新的时候,也需要获取登录信息以确定这个页面的访问用户是登陆过的。如果每次都需要用户重新登录,那么这种体验就太烂了,需要一种机制把之前用户登陆的信息保存起来,而且一定是保存在浏览器可以访问的本地存储上,这样,用户在页面跳转或者页面刷新的时候,登录信息被网站自动读取,就不需要用户频繁登录了。而这个保存的地方,叫做cookie。

爬虫需要做的事情,一是模拟登陆,拿到cookie数据,然后保存下来,二是每次去访问网页的时候,将cookie信息传递给请求,这样就可以正常爬到需要用户登录的数据了。

我们先设计一个登录类,用来管理登录的请求和数据

代码解释

用户名username, 密码password, 目标网站的登录页面地址login_url, 目标网站的主域名post_url_prefix,这些参数从外部传入,目标网站的登录页面地址也有可能就是网站的主页地址。

getpostdata首先向目标网站的登录页面地址发起一个请求,然后解析这个页面的数据,解析出登录请求的目标地址和post请求的数据(登录请求一般为post请求),然后返回这两个参数

设计一个方法,这个方法用来获取爬取网页请求需要的cookie数据。

user_name password login_url post_url_prefix 分别定义了用户名/密码/登录页面地址/目标网页前缀

如果从cookies_file读取出的cookie信息为空,那么就调用login做登录流程,并且把获取到的结果保存,如果cookie不为空,就返回cookie信息到字典cookiesdict中

pyspider每次爬取请求都带上cookie字典,这样,向目标地址发请求就可以获取到需要登录才能访问到的数据了。

如何解析爬取下来的内容

爬取的内容通过回调的参数response返回,response有多种解析方式

如果返回的数据是json,则可以通过response.json访问

response.doc返回的是pyquery对象

response.etree返回的是lxml对象

response.text返回的是unicode文本

response.content返回的是字节码

所以返回数据可以是5种形式,unicode和字节码不是结构化的数据,很难解析,这里就不赘述了,json需要特定的条件,而且解析相对简单,也不必说。

xpath选择器参考

选择器

示例

示例说明

nodename

bookstore

选择所有名称叫做”bookstore”的节点

/

bookstore/book

选择”bookstore”的节点的所有”book”子节点

//

//book

选择文档中所有名称叫做”book”的节点,不管它们的父节点叫做什么

.

选择当前的节点

..

选择当前节点的父节点

@

//@lang

选择所有名称叫做”lang”的属性

bookstore//book

选择节点”bookstore”所有叫做”book”的子孙节点,bookstore不一定是book的父节点

/bookstore/book[1]

选择节点”bookstore”的第一个叫做”book”的子节点

/bookstore/book[last()]

选择节点”bookstore”的最后一个叫做”book”的子节点

//title[@lang]

选择所有有一个属性名叫做”lang”的title节点

//title[@lang=’en’]

选择所有有一个属性”lang”的值为”en”的title节点

*

/bookstore/*

选择”bookstore”节点的所有子节点

//*

选择文档中所有的节点

@*

//title[@*]

选择所有的”title”节点至少含有一个属性,属性名称不限

pyquery可以采用css选择器作为参数对网页进行解析。

类似这样

或者这样

.class

.intro

selects all elements with class=”intro”

#id

#firstname

selects the element with id=”firstname”

element

p

selects all &lt;p&gt; elements

element,element

div, p

selects all &lt;div&gt; elements and all &lt;p&gt; elements

element element

div p

selects all &lt;p&gt; elements inside &lt;div&gt; elements

element&gt;element

div &gt; p

selects all &lt;p&gt; elements where the parent is a &lt;div&gt; element

[attribute]

[target]

selects all elements with a target attribute

[attribute=value]

[target=_blank]

selects all elements with target=”_blank”

[attribute^=value]

a[href^=”https”]

selects every &lt;a&gt; element whose href attribute value begins with “https”

[attribute$=value]

a[href$=”.pdf”]

selects every &lt;a&gt; element whose href attribute value ends with “.pdf”

[attribute*=value]

a[href*=”w3schools”]

selects every &lt;a&gt; element whose href attribute value contains the substring “w3schools”

:checked

input:checked

selects every checked &lt;input&gt; element

如何将数据保存到mysql中

将mysql的数据库访问封装成一个类

在处理爬取结果的回调中保存到数据库

如何在爬虫脚本更新后重新运行之前执行过的任务

比如这种场景,爬取了一些数据,发现没有写保存到数据库的逻辑,然后加上了这段逻辑,却发现之前跑过的任务不会在执行了。那么如何做到在爬虫脚本改动后,之前的任务重新自动再跑一遍呢。

在crawl_config中使用itag来标示爬虫脚本的版本号,如果这个值发生改变,那么所有的任务都会重新再跑一遍。示例代码如下

如何解析javascript代码

具体如何使用的可以看官方文档,这里列举出一些可供参考的javascript解析器

<a target="_blank" href="http://www.nightmarejs.org/">nightmare</a>

<a target="_blank" href="http://www.seleniumhq.org/">selenium</a>

<a target="_blank" href="https://github.com/makinacorpus/spynner">spynner</a>

<a target="_blank" href="https://github.com/jeanphix/ghost.py">ghost.py</a>

参考资料

<a target="_blank" href="https://github.com/binux/pyspider">binux/pyspider</a>

<a target="_blank" href="http://docs.pyspider.org/en/latest/">pyspider官方文档</a>

<a target="_blank" href="http://blog.binux.me/2014/02/pyspider-architecture/">pyspider架构设计</a>

<a target="_blank" href="http://www.jishubu.net/yunwei/python/411.html">pyspider中文脚本编写指南</a>

<a target="_blank" href="http://www.cnblogs.com/panliu/p/4524157.html">pyspider爬虫教程</a>

<a target="_blank" href="http://www.jishubu.net/yunwei/python/424.html">把 pyspider的结果存入自定义的mysql数据库中</a>

<a target="_blank" href="http://blog.csdn.net/u012293522/article/details/44222207">pyspider的mysql数据存储接口</a>

<a target="_blank" href="https://pythonhosted.org/pyquery/api.html">pyquery complete api</a>

<a target="_blank" href="http://www.w3schools.com/cssref/css_selectors.asp">css selector reference</a>

收集的一些其它网络爬虫的资料

java

<a target="_blank" href="https://github.com/decaywood/xueqiusuperspider">雪球股票信息超级爬虫</a>

<a target="_blank" href="https://github.com/mrjiao/spiderjackson">一个简单易用的爬虫框架,内置代理管理模块,灵活设置多线程爬取</a>

<a target="_blank" href="https://github.com/code4craft/webmagic">a scalable web crawler framework for java</a>

<a target="_blank" href="https://git.oschina.net/l-weiwei/spiderman2">强力 java 爬虫,列表分页、详细页分页、ajax、微内核高扩展、配置灵活</a>

python

<a target="_blank" href="http://scrapy.org/">scrapy</a>

<a target="_blank" href="https://github.com/ferventdesert/etlpy">a smart stream-like crawler &amp; etl python library</a>

<a target="_blank" href="https://you-get.org/">爬视频音频神器you-get</a>

<a target="_blank" href="https://github.com/rg3/youtube-dl">另一款视频下载神器youtube-dl</a>

<a target="_blank" href="https://github.com/mrs0m30n3/youtube-dl-gui">youtube-dl图形界面版</a>

<a target="_blank" href="https://github.com/thoxvi/mycar_python">自动抓取tumblr指定用户视频分享</a>

<a target="_blank" href="https://github.com/jmg/crawley">crawley</a>

<a target="_blank" href="https://github.com/hanc00l/wooyun_public">乌云公开漏洞、知识库爬虫和搜索</a>

<a target="_blank" href="https://github.com/dixudx/tumblr-crawler">下载指定的 tumblr 博客中的图片,视频</a>

<a target="_blank" href="https://github.com/xuanhun/tumblr-crawler">下载指定的 tumblr 博客中的图片,视频,玄魂修改版</a>

<a target="_blank" href="https://github.com/78/ssbc">dht网络爬虫</a>

<a target="_blank" href="https://github.com/dontcontactme/doubanspiders">豆瓣电影、书籍、小组、相册、东西等爬虫集 writen in python</a>

<a target="_blank" href="http://zpz.name/2378/">如何不用客户端下载 youku 视频-youku 实现下载 python3 实现</a>

<a target="_blank" href="https://github.com/yijingping/unicrawler">一个可配置的、分布式的爬虫框架</a>

<a target="_blank" href="https://github.com/scrapinghub">cloud-based web crawling platform</a>

<a target="_blank" href="https://github.com/x-spiders/baiduyun-spider">百度云爬虫-爬取百度云/百度网盘所有的分享文件</a>

<a target="_blank" href="https://github.com/x-spiders/aiss-spider">爱丝app图片爬虫,以及免支付破解vip看图</a>

<a target="_blank" href="https://github.com/bowenpay/wechat-spider">微信公众号爬虫</a>

<a target="_blank" href="https://github.com/whatsghost/lagou_spider">拉勾网爬虫</a>

<a target="_blank" href="https://www.v2ex.com/t/348731#reply7">百度网盘爬虫(如何爬取百度网盘)</a>

php

<a target="_blank" href="https://sourceforge.net/projects/php-crawler/">php crawler</a>

<a target="_blank" href="https://sourceforge.net/projects/phpcrawl/">phpcrawl</a>

<a target="_blank" href="https://github.com/fanfank/phpfetcher">phpfetcher</a>

<a target="_blank" href="https://github.com/hirudy/tspider">php spider framework</a>

<a target="_blank" href="https://github.com/owner888/phpspider">我用爬虫一天时间“偷了”知乎一百万用户,只为证明php是世界上最好的语言</a>

<a target="_blank" href="https://github.com/slince/spider">爬虫组件</a>

<a target="_blank" href="http://simplehtmldom.sourceforge.net/">php simple html dom parser</a>

<a target="_blank" href="https://querylist.cc/">querylist</a>

<a target="_blank" href="https://github.com/friendsofphp/goutte">goutte, a simple php web scraper</a>

nodejs

<a target="_blank" href="https://github.com/xwartz/spider">nodejs 编写的爬虫工具</a>

<a target="_blank" href="https://github.com/raawaa/jav-scrapy">批量抓取av磁链或封面的苦劳力</a>

<a target="_blank" href="https://github.com/leeiio/tumblr-downloader">easily download all the photos from a tumblr blog.</a>

<a target="_blank" href="https://github.com/dontcontactme/p2pspider">dht spider + bittorrent client = p2p spider</a>

<a target="_blank" href="https://github.com/callmelanmao/btspider">p2p spider修改版,添加了babel,eslint,gulp等工具来支持es6代码</a>

<a target="_blank" href="https://github.com/nieheyong/hanhandespider">一个node.js福利图网站爬虫程序</a>

<a target="_blank" href="https://github.com/beilunyang/dhtcrawler">一个简单的dht爬虫,用于搜集infohash</a>

<a target="_blank" href="https://github.com/callmelanmao/yunshare">百度云分享爬虫项目</a>

ruby

<a target="_blank" href="https://github.com/dontcontactme/rbdht">a simple dht crawler, written in ruby</a>

c sharp

<a target="_blank" href="https://github.com/ferventdesert/hawk">visualized crawler &amp; etl ide written with c#/wpf</a>

erlang

<a target="_blank" href="https://github.com/kevinlynx/dhtcrawler2">使用erlang实现p2p磁力搜索</a>

c++

<a target="_blank" href="https://github.com/yangyangwithgnu/hardseed">给不了你梦中情人,至少还有硬盘女神:hardseed</a>

golang

<a target="_blank" href="https://github.com/henrylee2cn/pholcus">a distributed, high concurrency and powerful web crawler software</a>

网络爬虫专题

<a target="_blank" href="http://www.open-open.com/lib/list/96">open-open 网络爬虫专题</a>

<a target="_blank" href="https://github.com/x-spiders">你想要的爬虫,都在这里</a>