Scrapy 是一个快速的高层次的屏幕抓取和网页爬虫框架,爬取网站,从网站页面得到结构化的数据,它有着广泛的用途,从数据挖掘到监测和自动测试,Scrapy完全用Python实现,完全开源,代码托管在Github上,可运行在Linux,Windows,Mac和BSD平台上,基于Twisted的异步网络库来处理网络通讯,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片。
安装Scrapy
1 | $ sudo pip install Scrapy |
scrapy依赖 lxml
,请保证已经安装了 lxml
库。
创建
初始化项目框架
这里以抓取 http://www.cnbeta.com/topics/9.htm
页面中的文章标题和简介为例,创建项目名称为 cnbetaSpider
。
1 | $ scrapy startproject cnbetaSpider |
该命令将会创建包含下列内容的 cnbetaSpider
目录:
1 | cnbetaSpider/ |
这些文件分别是:
scrapy.cfg
: 项目的配置文件cnbetaSpider/
: 该项目的python模块。之后您将在此加入代码。cnbetaSpider/items.py
: 项目中的item文件.cnbetaSpider/pipelines.py
: 项目中的pipelines文件.cnbetaSpider/settings.py
: 项目的设置文件.cnbetaSpider/spiders/
: 放置spider代码的目录.
定义Item
Item
是保存爬取到的数据的容器。我们需要从网页中提取 文章的标题,链接,描述,对此,在 item
中定义相应的字段。编辑 cnbetaSpider
目录中的 items.py
文件:
1 | import scrapy |
创建Spider
Spider
是用户编写用于从单个网站(或者一些网站)爬取数据的类。
其包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容, 提取生成 item
的方法。
为了创建一个 Spider
,您必须继承 scrapy.Spider
类, 且定义以下三个属性:
name
指定Spider的名称,唯一start_urls
包含了Spider在启动时进行爬取的url列表parse()
接收完成下载后生成的Response
对象,该方法负责解析返回的数据,提取数据(生成item)以及生成需要进一步处理的URL的Request
对象。
在目录 cnbetaSpider/spiders
下创建文件 cnbetaspider.py
:
1 | # coding:utf-8 |
爬取
进入项目根目录,执行下列命令启动spider:
1 | $ ls |
第三个参数为 cnbetaspider.py
中的 name
属性值。
执行完成后可在当前目录下看到生成的文件 topics
,里面保存的获取到的网页的内容。
提取
Scrapy使用了一种基于 XPath
和 CSS
表达式机制: Scrapy Selectors
。详见:选择器(Selectors) — Scrapy 0.24.1 文档
选择器方法( .xpath()
or .css()
)
为了提取真实的原文数据,你需要调用 .extract()
方法:
1 | >>> response.xpath('//title/text()').extract() |
这里给出XPath表达式的例子及对应的含义:
/html/head/title
: 选择HTML文档中<head>
标签内的<title>
元素/html/head/title/text()
: 选择上面提到的<title>
元素的文字//td
: 选择所有的<td>
元素//div[@class="mine"]
: 选择所有具有class="mine"
属性的div
元素
Selector有四个基本的方法:
xpath()
: 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表 。css()
: 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表.extract()
: 序列化该节点为unicode字符串并返回list。re()
: 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。
分析网页 http://www.cnbeta.com/topics/9.htm
中的文章:
文章列表在 item
元素:
1 | //*[@class="all_news_wildlist"]/div[@class="items"]/div[@class="item"] |
标题:
1 | xpath('//*[@class="all_news_wildlist"]/div[@class="items"]/div[@class="item"]/*[@class="hd"]/div[@class="title"]/a/text()').extract() |
链接:
1 | xpath('//*[@class="all_news_wildlist"]/div[@class="items"]/div[@class="item"]/*[@class="hd"]/div[@class="title"]/a/@href').extract() |
描述:
1 | xpath('//*[@class="all_news_wildlist"]/div[@class="items"]/div[@class="item"]/*[@class="hd"]/*[@class="newsinfo"]/p/text()').extract() |
修改我们之前定义的 cnbetaspider.py
中的 parse()
方法如下:
1 | import scrapy |
再次执行,能看到爬取到的网站信息被成功输出:
1 | $ scapy crawl cnbeta |
结果
将之前设置的 Item
对象引入,使用标准的字典语法来保持获取到的每个字段的值。最终的代码为:
1 | # coding:utf-8 |
如果想把得到的结果保存在临时文件中,可以:
1 | $ scrapy crawl cnbeta > abc.html |
这样就把结果保存在当前目录下的 abc.html
中了。
Scrapy爬虫运行时报错 “Forbidden by robots.txt”
解决该问题只需要将 settings.py
文件中的 ROBOTSTXT_OBEY
值改为 False
即可。
1 | ROBOTSTXT_OBEY = False |