网页爬虫--scrapy入门

本篇从实际出发,展现如何用网页爬虫。并介绍一个流行的爬虫框架~html


1. 网页爬虫的过程

所谓网页爬虫,就是模拟浏览器的行为访问网站,从而得到网页信息的程序。正由于是程序,因此得到网页的速度能够轻易超过单身多年的手速:)。一般适用于须要大量网页信息的场合。python

爬取网页的流程为:访问初始url -> 得到返回的网页,从这个网页中获得新的url并放入待爬队列 -> 访问新的url -> ...依次循环。总体上来看就是一个广度优先的过程,固然,新的url也不必定非要从返回的网页中得到。算法

一个简单的网页爬虫应该包括如下部分:网页爬虫

  1. 一个url队列。咱们的爬虫从这个队列中读取url,并将新的url放入这个队列。这里最重要的是判重。简单的哈希就能达到判重的目的,可是为了节约空间(url的数量每每不少),通常使用bloomfilter的思想。bloomfilter与普通的哈希算法最大的不一样就是bloomfilter只须要一个bit来表示某个元素是否存在,因此能节约空间。bloomfilter有一个小缺点,即准确率并非百分百:判断一个元素是否是已经存在时,已有的有很小的可能会判断为不存在,可是没有的元素必定会判断为不存在。
  2. 网页爬取模块。须要能模拟浏览器发送请求。
  3. 网页分析模块。爬下来的是网页源码,能够用正则或者其余方法提取咱们须要的信息。
  4. 新的url生成模块。生成新的url,放入队列。

那么,最简单的爬虫就能够这么写:浏览器

import Queue

start_url = "http://www.cnblogs.com/rubinorth"
url_queue = Queue.Queue()  # url队列
url_queue.put(start_url) 

bloomfilter.put(start_url)
#### 一直循环到队列为空 ####
while(True):
    if url_queue.size() > 0:
        current_url = url_queue.get()  # 队首的url
        page = crawl(current_url)  # crawl为网页爬取模块,page是爬到的网页源代码
        next_urls = deal_page(page)  # deal_page为网页分析模块,next_urls是新的一些url
        
        for next_url in next_urls: 
            if not bloomfilter.has(next_url):  # 判重     
                bloomfilter.put(next_url)
                url_queue.put(next_url)
    else:
        break

2. 为何选用scrapy

scrapy是目前一个比较流行的爬虫框架,其基本原理与上面的爬虫是同样的,可是它提供了不少便利的功能。cookie

首先,先简要介绍一下scrapy各个模块之间的关系和整个框架运行的流程。是时候祭出那张scrapy的经典图了:
scrapy
从这张图上看,scrapy包含了如下模块:python爬虫

  1. scrapy engine,主引擎。在处理数据流时负责管理整个系统,同时各类事件的触发也由其负责。
  2. spider,即咱们的爬虫。主要的爬虫代码都在这部分中,包括发起请求,处理返回的网页等等。
  3. spider middleware,spider中间件。中间件的一种,主要工做对spider发送的request作一些处理。
  4. scheduler,调度器。上面说到的url队列就是调度器在管理,一方面接收spider发送的request请求,放入队列中;另外一方面会从队首取出request交由downloader去下载网页。
  5. downloader,下载器。将网页的html源码下载下来供以后的网页分析和信息提取。
  6. downloader middleware,下载器中间件。中间件的一种,在下在网页以前和以后都会运行,能够用来设置发送请求的header,cookies,代理ip以及处理一些错误返回的状况。
  7. item pipeline, 管道。一个网页被爬取下来并解析以后,其后续的信息存储之类的工做在pipeline中进行。固然也能够直接在spider中完成这些工做,但在pipeline中完成则显得整个项目结构清晰。

上面列出的里面spider,pipeline须要本身写,两种middleware须要的话能够本身添加本身写的。框架

光介绍给人感受比较空洞,那下面就让咱们来使用scrapy实现一个简单的爬虫吧。dom


3. scrapy实现爬虫

scrapy createproject cnblog_project

使用上面的命令建立一个scrapy工程以后,首先咱们要写的是spider。scrapy

class CnblogSpider(Spider):
    name = 'cnblog_spider'  # 爬虫名字
    allowed_domain = ['cnblogs.com']  # 容许的domain

    def __init__(self):
        self.start_urls = ['http://www.cnblogs.com/rubinorth']

    def start_requests(self):
        return [Request(url, callback=self.parse_page) for url in self.start_urls]

    # 分析爬取的页面并构造下一个页面的请求
    def parse_page(self, response):
        logging.info("parse : " + response.url)

        sel = Selector(response)
        item = CnblogItem()

        # 提取页面内容
        item['name'] = sel.xpath("//a[@id='Header1_HeaderTitle']/text()").extract()[0]
        yield item
        # 下一个页面的请求
        new_url = get_new_url(response.body)  # 根据源码分析出新的连接,需本身实现
        yield Request(new_url, callback=self.parse_page)

上面是一个简单的爬虫,start_urls是初始的url集合(上面只有一个),start_requests则根据start_urls构造Request,并交给调度器。parse_page中,response是返回的页面的源码;CnblogItem是scrapy提供的item组件,方便结构化地提取源码中的数据,而yield item则会将这个item交给管道;yield Request(new_url, callback=self.parse_page)则会发送一个新的Request,发起下一轮的爬取。
items.py中只要这么写:

class CnblogItem(scrapy.Item):
    name = scrapy.Field()

接着,咱们须要写pipelines.py

class CnblogPipeline(object):
    def process_item(self, item, spider):
        print item['name']
        return item

每一个pipeline都必须有process_item这个方法。上面咱们只是简单地打印出了name。return item是考虑到可能有多个pipeline(return了以后可让其余pipeline处理)。
最后,只须要修改settings.py便可:

...
ITEM_PIPELINES = {
   'yelp_project.pipelines.CnblogPipeline': 304,
}
...

须要在setting中打开本身的pipeline。
好了,一个简单的爬虫就这么写完了。注意咱们并无用到中间件,也不须要写本身的中间件。
最后, 命令行运行:

scrapy crawl cnblog_spider

参考资料

如何入门python爬虫

转载请注明出处:http://www.cnblogs.com/rubinorth/

相关文章
相关标签/搜索