Learning Scrapy(一)

2020-09-07 11:42:46 浏览数 (1)

  学习爬虫有一段时间了,从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的安装:

代码语言:javascript复制
$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

  如果想要获得最新版的话,可以使用:

代码语言:javascript复制
git clone https://github.com/scrapy/scrapy.git
cd scrapy
python setup.py install

  升级scrapy

代码语言:javascript复制
sudo pip install -upgrade scrapy
or
sudo easy_install --upgrade scrapy

  当然 也有人是想安装特定的版本的 那么可以使用命令:

代码语言:javascript复制
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文件如下:

代码语言:javascript复制
from scrapy import Item,Field


class Mych03Item(Item):
    Title = Field()
    Abstract = Field()
    Link = Field()

写爬虫文件

  定义了item之后,我们就可以写爬虫文件了,在spider文件夹中建立相应的文件,我们可以开始写爬虫了。 首先,在项目的根目录下根据basic模板创建一个名为basic的spider,后面的web指的是spider的可运行的域名:

代码语言:javascript复制
scrapy genspider –t basic basic web

在本项目中的命令是:

代码语言:javascript复制
scrapy genspider -t basic cnblog cnblogs

这样就在spiders文件夹中创建了一个cnblog.py的爬虫文件。

当然可以自己手写一个spider,但是从模板里创建可以省去不少的时间和减少出错机率,查看其他模板的命令: scrapy genspider -l 使用模板创建的文件如下:

代码语言:javascript复制
# -*- 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文件如下:

代码语言:javascript复制
# 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写入文件或者数据库中。

如果你看到这里,那么恭喜你,已经会写一个简单的爬虫了。

0 人点赞