Learning Scrapy(一)
学习爬虫有一段时间了,从Python的Urllib、Urlllib2到scrapy,当然,scrapy的性能且效率是最高的,自己之前也看过一些资料,在此学习总结下。
Scrapy介绍
关于scrapy
scrapy是一个健壮的,可以从网络上抓取数据的web框架,只需要一个配置文件就能组合各种组件和配置选项。同时,scrapy是一个基于事件的架构 因此我们可以级联很多操作,包括清理,组织,存储数据到数据库,导出数据等。
假设你现在要抓取一个网站,这个网站的每一页都有一百个条目,Scrapy可以毫不费劲地同时对这个网站发起16个请求,假如每个请求需要一秒钟来完成,就相当于每秒钟爬取16个页面,相当于每秒钟生成了1600个条目,假如要把这些条目同时存储到云上,每一个条目的存储需要3秒钟(假设的),为了处理这16个请求,就需要运行1600 *3 = 4800个并发的写入请求,对于一个传统的多线程程序来说,就需要转换成4800个线程,这会对系统造成极大的压力。而对于Scrapy来说,只要你的硬件过关, 4800个并发请求是没有问题的。
scrapy的优点
Scrapy已经发展了5年有多,已经变得成熟和稳定,除了上面提到的性能优点外,Scrapy还有以下几点优点:
1. Scrapy可以处理不完整的HTML
你可以在Scrapy中使用Beautiful Soup或者lxml,但Scrapy已经提供了selectors(一个在lxml的基础上提供了更高级的接口),可以高效地处理不完整的HTML代码。
2. 活跃的Scrapy社区
Scrapy拥有一个活跃的社区,尤其是在Stack Overflow(https://stackoverflow.com/questions/tagged/Scrapy)上有上千个问题的讨论,更多的社区论坛可以参考这里:http://Scrapy.org/community/
3. 由社区维护的具有良好架构的代码
Scrapy要求你用标准的方式去组织你的代码,所以你在与他人合作时,别人不用苦苦研究你那拥有奇淫技巧的爬虫。
4. 新特性越来越多且质量稳定
通过观察Scrapy的新闻发布页(http://doc.Scrapy.org/en/latest/news.html),就可以看到在增加的新特性和bug修正。
Scrapy基础
安装
我一直是在ubuntu下使用scrapy的 下面就说说ubuntu下scrapy的安装:
$sudo apt-get update
$ sudo apt-get install python-pip python-lxml python-crypto python-cssselect python-openssl python-w3lib python-twisted python-dev
libxml2-dev libxslt1-dev zliblg-dev libffi-dev libssl-dev
$ sudo pip install scrapy
如果想要获得最新版的话,可以使用:
git clone https://github.com/scrapy/scrapy.git
cd scrapy
python setup.py install
升级scrapy
sudo pip install -upgrade scrapy
or
sudo easy_install --upgrade scrapy
当然 也有人是想安装特定的版本的 那么可以使用命令:
sudo pip install scrapy==1.00
or
sudo easy_install scrapy==1.00
爬取过程 - URI^2IM
每个网站都是不一样的,那么使用scrapy爬取时势必会存在差异。但是,当使用scrapy爬取时,使用最多的是UR^2IM流程,分别是:URL,Request,Response,Items,More URLS。
URL
所有的爬虫都是从一个起始的URL(也就是你想要爬取的网站地址)开始,当你想要验证用xpath或者其它解析器来解析这个网页时,可以使用scrapy shell工具来分析。
scrapy shell(scrapy终端)是一个交互式的终端,在未启动spider的情况下尝试及调试爬取代码,主要测试Xpath和CSS表达式等,查看他们的工作方式以及从爬取的网页中提取数据,该终端在开发和调试spider时发挥着巨大的作用。
启动终端:scrapy shell <url>
使用该终端时,可使用一些快捷命令,如下:
| shelp | 打印可用对象及快捷命令的帮助列表 |
| fetch(request_or_url) | 根据给定的请求(request)或URL获取一个新的response,并更新 相关对象 |
| view(response) | 在本机的浏览器打开给定的response |
可用的scrapy对象,scrapy终端会根据下载的页面自动创建一些方便使用的对象,包括:
| crawler | 当前的crawler对象 |
| spider | 处理URL的spider |
| request | 最近获取到的页面的request对象 |
| response | 最近获取到的页面的response对象 |
| sel | 最近获取到的response构建的Selector对象 |
| settings | 当前的scrapy settings |
终端会话样例:爬取"https://baidu.com"的页面。输入:scrapy shell 'http://www.cnblogs.com/ybjourney/' --nolog,会显示相应的各个对象的值,进而在In [1]:中输入:sel.xpath('//div[@class="postTitle"]/a/text()').extract(),验证xpath表达式。
The Request and The Response(请求和响应)
在上面使用scrapy shell就会发现,只要我们输入一个URL,它就可以自动发送一个GET请求并返回结果。request是一个把url封装好的对象,response则是一个把网页返回结果封装好的对象,response.body的值是网页的源代码,response.url是网页的url地址,还有更多相关的属性。
Items
爬虫的目标不只是在爬取到网页的源代码,更重要的是提取网页的相关信息,对于这些内容,在scrapy中被封装为一个Item对象,然后从网页中提取信息来填充这个Item。
从网页中提取信息常用到的方式有很多,比如正则表达式(re),BeautifulSoup,Xpath等,我常用到的就这几种。
scrapy工程
上面我们学习了scrapy的一些基础知识,现在我们动手创建一个scrapy项目,写爬虫~
首先,用命令scrapy startproject yourproject新建一个项目。 cd yourproject
tree
该项目的目录如下:
__init__.py
items.py
pipelines.py
settings.py
spiders
__init__.py
scrapy.cfg
其中,spiders文件中主要是用来编写爬虫(spider)文件,定义了对某个特定网页的类。其它重要的文件包括:items.py,piplines.py,settings.py,分别的作用如下:
items.py:定义需要抓取并需要后期处理的数据,很像字典;
settings.py:文件配置scrapy,从而修改user-agent,设定爬取时间间隔,设置代理,配置各种中间件等,在反爬虫时会用到。
piplines.py:用于存放执行后期数据的功能,将数据的爬取和处理分开。items抓取数据之后送到pipline。
建立project就是不断的对这三个文件进行修改。
编写爬虫
在了解了scrapy项目的目录后,接下来就是编写爬虫了,在这里以爬取我博客园第一页的博客标题、摘要、博客链接为例进行说明。
定义item
爬虫之前,一定是要知道你需要爬取到什么内容,在items.py中定义抓取,在该文件中定义的item并不是一定要在每一个spider中填充,也不是全部同时使用,因为item中的字段可以在不同的spider文件中使用,也可以在一个spider文件的不同地方使用,你只需要在此定义你需要用到的字段,定义之后在任何时候都可以使用。在该例子中的items.py文件如下:
from scrapy import Item,Field class Mych03Item(Item):
Title = Field()
Abstract = Field()
Link = Field()
写爬虫文件
定义了item之后,我们就可以写爬虫文件了,在spider文件夹中建立相应的文件,我们可以开始写爬虫了。
首先,在项目的根目录下根据basic模板创建一个名为basic的spider,后面的web指的是spider的可运行的域名:
scrapy genspider –t basic basic web
在本项目中的命令是:
scrapy genspider -t basic cnblog cnblogs
这样就在spiders文件夹中创建了一个cnblog.py的爬虫文件。
当然可以自己手写一个spider,但是从模板里创建可以省去不少的时间和减少出错机率,查看其他模板的命令:
scrapy genspider -l
使用模板创建的文件如下:
# -*- coding: utf-8 -*-
import scrapy class BasicSpider(scrapy.Spider):
name = "basic"
allowed_domains = ["web"]
start_urls = (
'http://www.web/',
) def parse(self, response):
pass
对该spider文件中的几个变量做出说明:
name:定义的spider名字,该名字在执行这个爬虫文件时会用到,故应保持名字是唯一的;
allowed_domains:允许爬取的域名列表;
start_urls:爬虫的起始地址。
创建好了模板文件,就可以结合之前的内容,编写爬虫文件了,编写cnblog.py文件如下:
# coding:utf-8
import scrapy
from mych03.items import Mych03Item
from scrapy.selector import Selector
from scrapy.utils.response import get_base_url class CnblogSpider(scrapy.Spider):
name = "cnblog"
allowed_domains = ["cnblogs"]
start_urls = (
'http://www.cnblogs.com/ybjourney/default.html?page=1',
) def parse(self, response):
items = []
sel = Selector(response)
base_url = get_base_url(response)
postTitle = sel.css('div.postTitle')
postAbstract = sel.css('div.c_b_p_desc')
for index in range(len(postTitle)):
item = Mych03Item()
item['Title'] = postTitle[index].css("a").xpath(u'text()').extract()[0]
item['Link'] = postTitle[index].css('a').xpath('@href').extract()[0]
item['Abstract'] = postAbstract.xpath('text()').extract()[0]
return items
运行:scrapy crawl spidername
保存文件:scrapy crawl spider -o filename.json/csv
保存之后就可以在项目的根目录下找到你所保存的.csv或者.json文件了。
Spider的运行原理
我们写了爬虫文件,现在,结合scrapy项目文件目录,对Spider的运行原理进行说明:
首先要将指定的初始URL封装成Request对象,并且指定在网页返回该请求的内容后应该用哪个函数来处理网页的内容。一般都会调用start_request()函数,对start_urls中的URL分别生成一个Request对象,并使用callback变量指定相应的parse()函数作为回调函数。
在回调函数中,处理response变量,返回item对象,一个字典,或者Request对象(可以指定callback,指定一个回调函数,也就是在处理完这个Request之后生成的response会传送到回调函数中处理)。
在回调函数中,使用Xpath等类提取网页中需要的内容,存入item。
从spider中返回的item写入文件或者数据库中。
如果你看到这里,那么恭喜你,已经会写一个简单的爬虫了。
Learning Scrapy(一)的更多相关文章
- Learning Scrapy笔记(六)- Scrapy处理JSON API和AJAX页面
摘要:介绍了使用Scrapy处理JSON API和AJAX页面的方法 有时候,你会发现你要爬取的页面并不存在HTML源码,譬如,在浏览器打开http://localhost:9312/static/, ...
- Learning Scrapy笔记(零) - 前言
我已经使用了scrapy有半年之多,但是却一直都感觉没有入门,网上关于scrapy的文章简直少得可怜,而官网上的文档(http://doc.scrapy.org/en/1.0/index.html)对 ...
- Learning Scrapy笔记(三)- Scrapy基础
摘要:本文介绍了Scrapy的基础爬取流程,也是最重要的部分 Scrapy的爬取流程 Scrapy的爬取流程可以概括为一个方程式:UR2IM,其含义如下图所示 URL:Scrapy的运行就从那个你想要 ...
- Learning Scrapy笔记(七)- Scrapy根据Excel文件运行多个爬虫
摘要:根据Excel文件配置运行多个爬虫 很多时候,我们都需要为每一个单独的网站编写一个爬虫,但有一些情况是你要爬取的几个网站的唯一不同之处在于Xpath表达式不同,此时要分别为每一个网站编写一个爬虫 ...
- Learning Scrapy笔记(五)- Scrapy登录网站
摘要:介绍了使用Scrapy登录简单网站的流程,不涉及验证码破解 简单登录 很多时候,你都会发现你需要爬取数据的网站都有一个登录机制,大多数情况下,都要求你输入正确的用户名和密码.现在就模拟这种情况, ...
- Learning Scrapy笔记(一)- Scrapy简单介绍
Scrapy简述 Scrapy十一个健壮的,用来从互联网上抓取数据的web框架,Scrapy只需要一个配置文件就能组合各种组件和配置选项,并且Scrapy是基于事件(event-based)的架构,使 ...
- Learning Scrapy 中文版翻译 第一章
第一章:scrapy介绍 欢迎来到scrapy之旅.通过这本书,我们将帮助你从只会一点或者零基础的Scrapy初学者达到熟练使用这个强大的框架在互联网或者其他资源抓取海量的数据.在这一章节,我们将给你 ...
- Learning Scrapy 中文版翻译 第二章
为了从网页中提取信息,你有必要对网页的结构做一些了解.我们将快速学习HMTL,HTML数状结构以及用XPath在网页上提取信息 HTML, DOM树结构以及XPath 让我们花一点时间来了解当用户在浏 ...
- Django学习(2)数据宝库
数据库是一所大宝库,藏着各种宝贝.一个没有数据库的网站,功能有限.在Django中,支持的数据库有以下四种: SQLite3 MySQL PostgreSQL Oracle 其中SQLite3为Dja ...
随机推荐
- SaltStack日常维护-第七篇
练习内容 远程执行其他模块 官方模块有很多超过300+ 1.cmd.run 2.network 3.service 4.state 5.其它日常维护 演示 cmd.run模块 可以执行系统命令,超级模 ...
- System.IO命名空间下常用的类
System.IO System.IO.Directory 目录 System.IO.Path 文件路径(包含目录和文件名) System.IO.FileInfo 提供创建.复制.删除.移动和打开文件 ...
- 搭建Nginx图片服务器(Linux)
知识点: 在Linux系统上安装Nginx服务器,配置图片访问路径 通过ftp上传图片到,指定路径,通过浏览器访问指定路径中的图片 参考博客:http://blog.csdn.net/maoyuanm ...
- 商品详情页,banner滚动点击加载效果,js,jquary
<script language="javascript"> $(document).ready(function () { //purchase ...
- codeforces741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- codeforces600E Lomsat gelral
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- Linux命令详解-mkdir
linux mkdir 命令用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 1.命令格式: mkdir [选项] 目录... 2.命令 ...
- Java MongoDB插入
前言 插入是向MongoDB中添加数据的基本方法.对目标集使用insert方法来插入一条文档.这个方法会给文档增加一个”_id”属性(如果原来没有的话),然后保存到数据库中. 1.连接数据库,拿到集合 ...
- [Java基础] 深入jar包:从jar包中读取资源文件
转载: http://hxraid.iteye.com/blog/483115?page=3#comments 我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等).在单独运行的时候这些简单的 ...
- 016PHP基础知识——流程控制(四)
<?php /** * 流程控制(四) do...while * do{ 代码段 * }while(){ * } * 特点:最少会执行一次代码段 */ /*$i=5; do{ echo $i; ...