记得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. 创建工程
 
 
1
$ scrapy startproject my_crawler

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

 
 
1
2
3
4
5
6
7
8
my_crawler
  |- my_crawler
  |    |- spiders
  |    |    |- __init__.py
  |    |- items.py
  |    |- pipelines.py
  |    |- setting.py
  |- scrapy.cfg
    1. 设置待抓取内容的字段,本例中就是文章的标题,地址和摘要

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

 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
# -*- coding: utf-8 -*-
import scrapy
 
class MyCrawlerItem(scrapy.Item):
    title = scrapy.Field()    # 文章标题
    url = scrapy.Field()      # 文章地址
    summary = scrapy.Field()  # 文章摘要
    pass
    1. 编写网页解析代码

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

 
 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# -*- 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。

    1. 让我们测试下爬虫的效果

在命令行中输入:

 
 
1
$ scrapy crawl my_crawler

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

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

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

 
 
1
$ scrapy crawl my_crawler -o my_crawler.json -t json

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

    1. 将结果保存到数据库

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

 
 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# -*- 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, item, spider):
        valid = True
        for data in item:
            if not data:  # 过滤掉存在空字段的项
                valid = False
                raise DropItem("Missing {0}!".format(data))
 
        if valid:
            # 也可以用self.collection.insert(dict(item)),使用upsert可以防止重复项
            self.collection.update({'url': item['url']}, dict(item), upsert=True)
 
        return item

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

 
 
 
 
 
 

Python

 
1
2
3
4
5
6
7
8
9
10
11
ITEM_PIPELINES = {
    'my_crawler.pipelines.MyCrawlerPipeline': 300,    # 设置Pipeline,可以多个,值为执行优先级
}
 
# MongoDB连接信息
MONGO_SERVER = 'localhost'
MONGO_PORT = 27017
MONGO_DB = 'bjhee'
MONGO_COLLECTION = 'articles'
 
DOWNLOAD_DELAY=2    # 如果网络慢,可以适当加些延迟,单位是秒
    1. 执行爬虫
 
 
1
$ scrapy crawl my_crawler

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

总结下,使用Scrapy来构建一个网络爬虫,你需要做的就是:厦门叉车租赁公司

  • “items.py”中定义爬取字段
  • 在”spiders”目录下创建你的爬虫,编写解析函数和规则
  • “pipelines.py”中对爬取后的结果做处理
  • “settings.py”设置必要的参数

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

本例中的代码可以在这里下载

最新文章

  1. YII2之 Scenario
  2. AMD and CMD are dead之KMDjs内核之分号
  3. go语言 hello 小结
  4. android setVisibility失效不起作用的问题
  5. android关于installLocation
  6. 选择排序(Selection Sort)
  7. IDEA2017.3.3创建第一个javaweb项目及tomcat部署实战
  8. Jenkins XVnc Plugin
  9. ActiveX 控件导入程序
  10. 获取linux工具命令源码
  11. 二叉堆的实现(数组)——c++
  12. 初学Cocos2dx
  13. 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 D.寻找-树上LCA(树上a到b的路径上离c最近的点)
  14. python操作adb代码
  15. 51 Nod 1042 数位dp
  16. 微信小程序之日期与时间插件
  17. C# 字符串操作,可空类型,文档注释,嵌套类型
  18. Nacicat for Oracle 绿色版 亲测可用
  19. Repeater控件最后一笔记录高亮显示
  20. 计蒜客 28315.Excellent Engineers-线段树(单点更新、区间最值) (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 E)

热门文章

  1. --oracle删除数据库表(无主键)中重复的记录
  2. C# 自定义特性Attribute
  3. Linux常用命令拾遗
  4. PetaLinux安装及使用
  5. Windows下安装配置MinGW GCC调试环境
  6. 141. Sqrt(x)【牛顿迭代法求平方根 by java】
  7. drag element
  8. Swift里performSelector方法的替代
  9. Hadoop安装配置
  10. 20155330 实验三 敏捷开发与XP实践