使用Scrapy构建一个网络爬虫

铁扇公主1 发布于 2017/05/04 22:20
阅读 115
收藏 1

记得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,具体的方法是在命令行执行下面的命令即可。

1

$xcode-select--install

环境安装好之后,我们来用Scrapy实现一个简单的爬虫,抓取本博客网站的文章标题,地址和摘要。

创建工程

1

$scrapystartprojectmy_crawler

该命令会在当前目录下创建一个名为”my_crawler”的工程,工程的目录结构如下

 

8my_crawler

|-my_crawler

||-spiders

|||-__init__.py

||-items.py

||-pipelines.py

||-setting.py

|-scrapy.cfg

设置待抓取内容的字段,本例中就是文章的标题,地址和摘要

修改”items.py”文件,在”MyCrawlerItem”类中加上如下代码:

Python

 

8# -*- coding: utf-8 -*-

importscrapy

classMyCrawlerItem(scrapy.Item):

title=scrapy.Field()# 文章标题

url=scrapy.Field()# 文章地址

summary=scrapy.Field()# 文章摘要

pass

编写网页解析代码

在”my_crawler/spiders”目录下,创建一个名为”crawl_spider.py”文件(文件名可以任意取)。代码如下

Python

 

 

31# -*- coding: utf-8 -*-

importscrapy

fromscrapy.linkextractorsimportLinkExtractor

fromscrapy.spidersimportCrawlSpider,Rule

frommy_crawler.itemsimportMyCrawlerItem

classMyCrawlSpider(CrawlSpider):

name='my_crawler'# Spider名,必须唯一,执行爬虫命令时使用

allowed_domains=['bjhee.com']# 限定允许爬的域名,可设置多个

start_urls=[

# 种子URL,可设置多个

]

rules=(# 对应特定URL,设置解析函数,可设置多个

Rule(LinkExtractor(allow=r'/page/[0-9]+'),# 指定允许继续爬取的URL格式,支持正则

callback='parse_item',# 用于解析网页的回调函数名

follow=True

),

)

defparse_item(self,response):

# 通过XPath获取Dom元素

articles=response.xpath('//*[@id="main"]/ul/li')

forarticleinarticles:

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]

yielditem

对于XPath不熟悉的朋友,可以通过Chrome的debug工具获取元素的XPath。

让我们测试下爬虫的效果

在命令行中输入:

1

$scrapycrawlmy_crawler

注意,这里的”my_crawler”就是你在”crawl_spider.py”文件中起的Spider名。

没过几秒钟,你就会看到要抓取的字段内容打印在控制台上了。就是这么神奇!Scrapy将HTTP(S)请求,内容下载,待抓取和已抓取的URL队列的管理都封装好了。你的主要工作基本上就是设置URL规则及编写解析的方法。

我们将抓取的内容保存为JSON文件:

1

$scrapycrawlmy_crawler-omy_crawler.json-tjson

你可以在当前目录下,找到文件”my_crawler.json”,里面保存的就是我们要抓取的字段信息。(参数”-t json”可以省去)

将结果保存到数据库

这里我们采用MongoDB,你需要先安装Python的MongoDB库”pymongo”。编辑”my_crawler”目录下的”pipelines.py”文件,在”MyCrawlerPipeline”类中加上如下代码:

Python

 

29# -*- coding: utf-8 -*-

importpymongo

fromscrapy.confimportsettings

fromscrapy.exceptionsimportDropItem

classMyCrawlerPipeline(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项

defprocess_item(self,item,spider):

valid=True

fordatainitem:

ifnotdata:# 过滤掉存在空字段的项

valid=False

raiseDropItem("Missing {0}!".format(data))

ifvalid:

# 也可以用self.collection.insert(dict(item)),使用upsert可以防止重复项

self.collection.update({'url':item['url']},dict(item),upsert=True)

returnitem

再打开”my_crawler”目录下的”settings.py”文件,在文件末尾加上pipeline的设置:

Python

 

11ITEM_PIPELINES={

'my_crawler.pipelines.MyCrawlerPipeline':300,# 设置Pipeline,可以多个,值为执行优先级

}

# MongoDB连接信息

MONGO_SERVER='localhost'

MONGO_PORT=27017

MONGO_DB='bjhee'

MONGO_COLLECTION='articles'

DOWNLOAD_DELAY=2# 如果网络慢,可以适当加些延迟,单位是秒

执行爬虫

1

$scrapycrawlmy_crawler

别忘了启动MongoDB并创建”bjhee”数据库哦。现在你可以在MongoDB里查询到记录了。

总结下,使用Scrapy来构建一个网络爬虫,你需要做的就是:

“items.py”中定义爬取字段

在”spiders”目录下创建你的爬虫,编写解析函数和规则

“pipelines.py”中对爬取后的结果做处理

“settings.py”设置必要的参数

其他的事情,Scrapy都帮你做了。下图就是Scrapy具体工作的流程。怎么样?开始写一个自己的爬虫吧。

 

学好python你需要一个良好的环境,一个优质的开发交流群,群里都是那种相互帮助的人才是可以的,我有建立一个python学习交流群,在群里我们相互帮助,相互关心,相互分享内容,这样出问题帮助你的人就比较多,群号是301,还有056,最后是051,这样就可以找到大神聚合的群,如果你只愿意别人帮助你,不愿意分享或者帮助别人,那就请不要加了,你把你会的告诉别人这是一种分享。如果你看了觉得还可以的麻烦给我点个赞谢谢

学习是对自己最好的投资,而机会属于有准备的人,这是一个看脸的时代,但最终拼的是实力。人和人之间的差距不在于智商,而在于如何利用业余时间,所以没有等出来的辉煌,只有干出来的精彩。其实只要你想学习,什么时候开始都不晚,不要担心这担心那,你只需努力,剩下的交给时间,而你之所以还没有变强,只因你还不够努力,要记得付出不亚于任何人的努力。

加载中
返回顶部
顶部