(点击
上方蓝字
,快速关注我们)
来源:思诚之道
www.bjhee.com/scrapy.html
如有好文章投稿,请点击 → 这里了解详情
记得n年前项目需要一个灵活的爬虫工具,就组织了一个小团队用Java实现了一个爬虫框架,可以根据目标网站的结构、地址和需要的内容,做简单的配置开发,即可实现特定网站的爬虫功能。因为要考虑到各种特殊情形,开发还耗了不少人力。后来发现了Python下有这个Scrapy工具,瞬间觉得之前做的事情都白费了。对于一个普通的网络爬虫功能,Scrapy完全胜任,并把很多复杂的编程都包装好了。本文会介绍如何Scrapy构建一个简单的网络爬虫。
一个基本的爬虫工具,它应该具备以下几个功能:
-
通过HTTP(S)请求,下载网页信息
-
解析网页,抓取需要的内容
-
保存内容
-
从现有页面中找到有效链接,从而继续抓取下一个网页
我们来看下Scrapy怎么做到这些功能的。首先准备Scrapy环境,你需要安装Python(本文使用v2.7)和pip,然后用pip来安装lxml和scrapy。个人强烈建议使用virtualenv来安装环境,这样不同的项目之间不会冲突。详细步骤这里就不赘述了。对于Mac用户要注意,当使用pip安装lxml时,会出现类似于的下面错误:
Error: #include “xml/xmlversion.h” not found
解决这个问题,你需要先安装Xcode的command line tools,具体的方法是在命令行执行下面的命令即可。
$ xcode-select --install
环境安装好之后,我们来用Scrapy实现一个简单的爬虫,抓取本博客网站的文章标题,地址和摘要。
1. 创建工程
$ scrapy startproject my_crawler
该命令会在当前目录下创建一个名为”my_crawler”的工程,工程的目录结构如下
my_crawler
|-
my_crawler
| |-
spiders
| | |-
__init__
.
py
| |-
items
.
py
| |-
pipelines
.
py
| |-
setting
.
py
|-
scrapy
.
cfg
2. 设置待抓取内容的字段,本例中就是文章的标题,地址和摘要
修改”items.py”文件,在”MyCrawlerItem”类中加上如下代码:
# -*- coding: utf-8 -*-
import
scrapy
class
MyCrawlerItem
(
scrapy
.
Item
)
:
title
=
scrapy
.
Field
()
# 文章标题
url
=
scrapy
.
Field
()
# 文章地址
summary
=
scrapy
.
Field
()
# 文章摘要
pass
3. 编写网页解析代码
在”my_crawler/spiders”目录下,创建一个名为”crawl_spider.py”文件(文件名可以任意取)。代码如下
# -*- coding: utf-8 -*-
import
scrapy
from
scrapy
.
linkextractors
import
LinkExtractor
from
scrapy
.
spiders
import
CrawlSpider
,
Rule
from
my_crawler
.
items
import
MyCrawlerItem
class
MyCrawlSpider
(
CrawlSpider
)
:
name
=
'my_crawler'
# Spider名,必须唯一,执行爬虫命令时使用
allowed_domains
=
[
'bjhee.com'
]
# 限定允许爬的域名,可设置多个
start_urls
=
[
"http://www.bjhee.com"
,
# 种子URL,可设置多个
]
rules
=
(
# 对应特定URL,设置解析函数,可设置多个
Rule
(
LinkExtractor
(
allow
=
r
'/page/[0-9]+'
),
# 指定允许继续爬取的URL格式,支持正则
callback
=
'parse_item'
,
# 用于解析网页的回调函数名
follow
=
True
),
)
def
parse_item
(
self
,
response
)
:
# 通过XPath获取Dom元素
articles
=
response
.
xpath
(
'//*[@id="main"]/ul/li'
)
for
article
in
articles
:
item
=
MyCrawlerItem
()
item
[
'title'
]
=
article
.
xpath
(
'h3[@class="entry-title"]/a/text()'
).
extract
()[
0
]
item
[
'url'
]
=
article
.
xpath
(
'h3[@class="entry-title"]/a/@href'
).
extract
()[
0
]
item
[
'summary'
]
=
article
.
xpath
(
'div[2]/p/text()'
).
extract
()[
0
]
yield
item
对于XPath不熟悉的朋友,可以通过Chrome的debug工具获取元素的XPath。
4. 让我们测试下爬虫的效果
在命令行中输入:
$ scrapy crawl my_crawler
注意,这里的”my_crawler”就是你在”crawl_spider.py”文件中起的Spider名。
没过几秒钟,你就会看到要抓取的字段内容打印在控制台上了。就是这么神奇!Scrapy将HTTP(S)请求,内容下载,待抓取和已抓取的URL队列的管理都封装好了。你的主要工作基本上就是设置URL规则及编写解析的方法。
我们将抓取的内容保存为JSON文件:
$ scrapy crawl my_crawler -o my_crawler.json -t json
你可以在当前目录下,找到文件”my_crawler.json”,里面保存的就是我们要抓取的字段信息。(参数”-t json”可以省去)
5. 将结果保存到数据库
这里我们采用MongoDB,你需要先安装Python的MongoDB库”pymongo”。编辑”my_crawler”目录下的”pipelines.py”文件,在”MyCrawlerPipeline”类中加上如下代码:
# -*- coding: utf-8 -*-
import
pymongo
from
scrapy
.
conf
import
settings
from
scrapy
.
exceptions
import
DropItem
class
MyCrawlerPipeline
(
object
)
:
def
__init__
(
self
)
:
# 设置MongoDB连接
connection
=
pymongo
.
Connection
(
settings
[
'MONGO_SERVER'
],
settings
[
'MONGO_PORT'
]
)
db
=
connection
[
settings
[
'MONGO_DB'
]]
self
.
collection
=
db
[
settings
[
'MONGO_COLLECTION'
]]
# 处理每个被抓取的MyCrawlerItem项
def
process_item
(
self
,