zoukankan      html  css  js  c++  java
  • 使用Scrapy构建一个网络爬虫

    记得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
     
      1. 设置待抓取内容的字段,本例中就是文章的标题,地址和摘要
    修改”items.py”文件,在”MyCrawlerItem”类中加上如下代码:
    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”文件(文件名可以任意取)。代码如下
    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. 让我们测试下爬虫的效果
    在命令行中输入:
    $ 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”可以省去)
      1. 将结果保存到数据库
    这里我们采用MongoDB,你需要先安装Python的MongoDB库”pymongo”。编辑”my_crawler”目录下的”pipelines.py”文件,在”MyCrawlerPipeline”类中加上如下代码:
    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的设置:
    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. 执行爬虫
    $ scrapy crawl my_crawler
    别忘了启动MongoDB并创建”bjhee”数据库哦。现在你可以在MongoDB里查询到记录了。
     
    总结下,使用Scrapy来构建一个网络爬虫,你需要做的就是:
    • “items.py”中定义爬取字段
    • 在”spiders”目录下创建你的爬虫,编写解析函数和规则
    • “pipelines.py”中对爬取后的结果做处理
    • “settings.py”设置必要的参数
    其他的事情,Scrapy都帮你做了。下图就是Scrapy具体工作的流程。怎么样?开始写一个自己的爬虫吧。
     
    本例中的代码可以在这里下载(http://www.bjhee.com/downloads/201511/my_crawler.tar.gz)。
  • 相关阅读:
    ASP.NET Web API 控制器执行过程(一)
    ASP.NET Web API 控制器创建过程(二)
    ASP.NET Web API 控制器创建过程(一)
    ASP.NET Web API WebHost宿主环境中管道、路由
    ASP.NET Web API Selfhost宿主环境中管道、路由
    ASP.NET Web API 管道模型
    ASP.NET Web API 路由对象介绍
    ASP.NET Web API 开篇示例介绍
    ASP.NET MVC 视图(五)
    ASP.NET MVC 视图(四)
  • 原文地址:https://www.cnblogs.com/allan-king/p/7094930.html
Copyright © 2011-2022 走看看