从零开始写爬虫

几个朋友对爬虫很感兴趣,他们也都是开发人员,一个PHP开发两个JAVA开发,都没有过python项目开发经验,正好其中一个最近要爬一个网店的产品信息,因此但愿我能拿这网站当demo写一个爬虫来给他们参考学习。要爬取的页是http://list.secoo.com/watches...,只要爬取产品相关了属性就能够。css

clipboard.png
这就是要爬取的相关信息html

爬虫框架使用的是python的scrapy,这也是我如今项目中使用的爬虫框架。朋友们因为没有使用过scrapy,所以推荐他们去看一下框架文档,http://scrapy-chs.readthedocs...,这是scrapy的入门教程,基本上看完前面几章就能快速开发一个简单的爬虫了。python

1、生成代码
scrapy提供了命令行工具来快速生成一个简单的爬虫,咱们也使用这个工具来快速生成代码。在终端下面运行下面的命令就能快速生成一个scrapy爬虫的基础框架,免去一些最原始的代码开发操做。mysql

scrapy startproject secoo

clipboard.png

生成的项目文件就是上面的样子,spiders目录是存放爬虫代码,items.py是定义爬虫要爬取的字段信息,pipelines.py是用来处理爬虫爬到的数据的,好比用来作保存操做,像是存redis或是mysql等等,settings.py是项目的基础配置文件,定义一些爬虫的全局参数。
生成完项目基础代码后还能够使用下面的命令行工具来生成爬虫代码最简单的代码,和建立项目同样,能够省去建立文件的麻烦。redis

scrapy genspider watch secoo.com

命令执行完成后咱们就会在spiders目录下发现咱们生成好的爬虫文件watch.py了。咱们就在这个文件里开发爬虫的相关逻辑。sql

2、 定义爬虫数据字段
爬虫要爬页面,确定是要从爬取到的页面中提取到咱们想要的字段信息,这样的话咱们就要先来定义一下哪些是咱们要的字段,后面好在本地保存,这个就是scrapy里的items来负责的。
咱们打开根目录下面的items.py文件,这个文件里定义一个SecooItem的类,咱们定义了4个字段,分别用来保存产品名、路径、价格和库存信息,这一步操做咱们就完成了,后面的爬虫按这个定义好的格式来保存数据就能够了。数据库

import scrapy

class SecooItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    product_name = scrapy.Field()       #产品名
    breadcrumb = scrapy.Field()         #面包屑路径
    product_price = scrapy.Field()      #产品价格
    product_stock = scrapy.Field()      #库存状态

3、定义保存数据操做
这一步是要来定义爬虫的数据提取出来之后,按照items.py定义的格式格式化之后是如何保存的。因为咱们是写一个demo给你们来参考,所以这一部分代码是没有写实际的数据保存操做的,咱们只定义了这个操做类,若是是想要进行保存数据操做的话能够直接修改SecooPipeline类的process_item方法,在这里能够和正常脚本操做数据库同样进行链接、写入操做的。json

class SecooPipeline(object):
    def process_item(self, item, spider):
        return item

4、页面爬取
最后一步就是最重要的一步了,咱们要进行爬虫逻辑的开发。在这里先贴上代码,而后再来解释每一步的操做。框架

# -*- coding: utf-8 -*-
import scrapy
from secoo.items import SecooItem

class WatchSpider(scrapy.Spider):
    name = 'watch'
    allowed_domains = ['secoo.com']
    start_urls = ['http://list.secoo.com/watches/93-0-0-0-0-1-0-0-1-10-0-908_0.shtml']


    def parse(self, response):
        '''
        解析商品列表页面的内容,提取商品页面连接并生成请求
        :param response:
        :return:
        '''
        #解析商品连接
        goods_links = response.css('body .product_box .commodity-list dl .show_tips dt>a::attr(href)').extract()

        for url in goods_links:
            #分别去爬取商品信息
            yield scrapy.Request(url, callback=self.parse_goods, dont_filter=True)

        next_page = self.get_next_page_url(response)
        if next_page:
            yield scrapy.Request(next_page, callback=self.parse)


    def get_next_page_url(self, response):
        '''
        获取下一个商品列表的连接
        :param response:
        :return:
        '''
        return response.css('a.next::attr(href)').extract_first()

    def parse_goods(self, response):
        '''
        解析商品内容,提取要爬取的字段
        :param response:
        :return:
        '''
        name = response.css('.sopdetailsCon .contents .info_r .proName h2::text').extract_first()
        price = response.css('#secooPriceJs::text').extract_first()
        stock = response.css('#youhuo::text').extract_first()
        breadcrumb = '->'.join(response.css('.smallNav p a::text').extract())

        yield SecooItem({
            'product_name': name,
            'breadcrumb': breadcrumb,
            'product_price': price,
            'product_stock': stock,
        })

在使用命令行工具生成爬虫的时候就会帮咱们定义好三个变量,一个是name,这个是定义爬虫的名称的;第二个是allowed_domains,这个是一个list,定义爬虫容许爬取的域名;最后一个start_urls变量也是一个list类型,是用来定义爬虫入口URL的,能够定义多个入口地址。
接下来是parse方法,这个方法是框架默认的第一个处理方法,用来解析网页内容的。大概的逻辑在注释中写的比较清楚,逻辑就是咱们解析那个产品列表页面,从其中提取产品列表连接,而后生成请求去爬取产品信息,而后再去提取产品列表页面的下一页连接,再生成请求去请求这个页面,处理回调方法就是parse方法,这样就能实现全部翻页爬取。
在parse方法里提取出来的产品连接生成了请求以后,我把爬虫回调处理方法设置成parse_goods,所以咱们要去定义一个parse_goods方法来处理产品页面html内容。经过xpath或是css的selector方法来提取咱们想要爬取的内容,而后丢给pipelines.py来处理了。这样咱们就把爬虫的全部逻辑实现完成了,最后一步不是验证爬虫的运行状况了。dom

5、运行
最后一步就是就是运行操做,咱们在命令行下,进入项目目录,而后执行下面命令就能正常运行爬虫了,因为咱们没有写保存操做,所以咱们就把数据导出到一个json文件里。

scrapy crawl watch --output=product.json

clipboard.png