####1、安装scrapy
建议:最好在新的虚拟环境里面安装scrapy
注意:博主是在 Ubuntu18.04 + Python3.6 环境下进行开发的,如果遇到安装scrapy不成功请自行百度/谷歌解决

pip install scrapy

顺便装上iPython 这样方便操作scrapy shell

pip install ipython

####2、scrapy入门讲解
先附上爬取原理图
这里写图片描述
(1)创建项目

通过指令来进行创建的
scrapy startproject firstSpider(项目名称)

(2)项目目录结构

firstSpider
	firstSpider
		spiders           爬虫目录(写代码位置)
			__init__.py   表示这是一个Python模块
			first.py      爬虫文件
		__init__.py
		items.py          定义数据结构地方
		middlewares.py    中间件
		pipelines.py      管道文件
		settings.py       项目配置文件
	scrapy.cfg
		通过指令创建爬虫文件
			cd firstSpider/firstSpider
			scrapy genspider qiubai "www.qiushibaike.com"
			那么就会在firstSpider/firstSpider/spiders里面自动创建一个qiubai.py
		name: 爬虫的名字,启动的时候根据爬虫的名字启动项目
		allowed_domains:允许的域名,就是爬取的时候这个请求要不要发送,如果是该允许域名之下的url,就会发送,如果不是,则过滤掉这个请求,这是一个列表,可以写多个允许的域名
		start_urls:爬虫起始url,是一个列表,里面可以写多个,一般只写一个
		def parse(self, response): 这个函数非常重要,就是你以后写代码的地方,parse函数名是固定的,当收到下载数据的时候会自动的调用这个方法,该方法第二个参数为response,这是一个响应对象,从该对象中获取html字符串,然后解析之。【注】这个parse函数必须返回一个可迭代对象

(3)定制items.py,其实就是您的数据结构,格式非常简单,复制粘贴即可
(4)打印response对象,简单跑一把

来到终端下:
cd firstSpider/firstSpider/spiders
scrapy crawl qiubai

根据response获取网页内容
response.text    字符串类型
response.body    二进制类型

(5)运行,直接通过命令导出json格式

scrapy crawl qiubai -o qiubai.json
scrapy crawl qiubai -o qiubai.xml
scrapy crawl qiubai -o qiubai.csv

(6)scrapy shell 的使用

scrapy shell
	运行在终端的工具,用来调试scrapy
	简单使用
	# 注意不能在已近创建好的scrapy目录下操作,否则返回的response为 none
	(1)scrapy shell "http://www.xiaohuar.com/hua/"
		response对象
			属性
				text:字符串格式的html
				body:二进制格式的html
				url:所请求的url
				status:响应的状态码
			方法:
				xpath(): 根据xpath路径获取符合的路径所有selector对象(是scrapy自己封装的一个类的对象)的列表
				css(): 根据选择器获取符合选择器要求的所有selector对象的列表
				获取内容的时候要这么写
					#detail-list > li .header > a > div > .name::text
				获取属性的方法要这么写
					#detail-list > li .header > a > div > .name::attr("data-src")
				下面接着extract()即可  
				一般不使用这个,因为中间scrapy会将这个选择器给翻译成xpath再去解析
			selector对象
				xpath('./'): 从当前节点向下开始查找 
				css(): 和上面的response的方式一样
				extract(): 将对象转化为unicode字符串,供你的代码使用
				extract_first(): 理论上相当于上面的  
					name_list.extract()[0] == name_list.extract_first()
					但实际上,extract_first()要比extract()强大,如果xpath没有获取到内容,extract_first()会返回None
	(2)item对象
		官方的这个Item其实就是一个类字典的对象,或者你就可以叫做它就是一个字典,用的时候和字典的用法一模一样
		将这个对象转化为字典
			pp = dict(p)

####3、实战-爬取校花网图片资源
1、settings.py文件的配置

# 使用的请求ua
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0(Macintosh;IntelMacOSX10.6;rv:2.0.1)Gecko/20100101Firefox/4.0.1'

# 是否遵循国际爬虫条例,个人写的爬虫不需要遵循
# Obey robots.txt rules
ROBOTSTXT_OBEY = False

# 设置的请求头
# Override the default request headers:
DEFAULT_REQUEST_HEADERS = {
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  # 'Accept-Language': 'en',
}

# Configure item pipelines
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
# 表示使用管道 这里300表示处理的优先级
# 你也可以自己再写一部分管道,然后设置优先级处理
ITEM_PIPELINES = {
   'huaproject.pipelines.HuaprojectPipeline': 300,
}
####剩余配置默认即可

2、items.py文件的处理

import scrapy


class HuaprojectItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 需要的数据现在这里制定好,因为在settings里面已近设置好了,所以可以和pipelines联系在一块处理数据
    # 图片链接
    image_url = scrapy.Field()
    # 名字
    name = scrapy.Field()
    # 大学
    school = scrapy.Field()
    # 喜欢数
    like = scrapy.Field()

3、关键爬虫文件xiaohua.py的处理

import scrapy
# 导入数据结构类
from huaproject.items import HuaprojectItem

class XiaohuaSpider(scrapy.Spider):
    name = 'xiaohua'
    allowed_domains = ['www.xiaohuar.com']
    # 基础url
    url = 'http://www.xiaohuar.com/list-1-'
    # 爬取的起始页
    page = 0
    # 爬取的起始url
    start_urls = ['http://www.xiaohuar.com/hua/list-1-0.html']

    # 定义的方法,注意这个方法名不能修改,传入的参数也不能修改,否则会出错
    def parse(self, response):
        # print(100)
        # 解析所有校花,获取指定内容
        div_list = response.xpath('//div[@class="item masonry_brick"]')
        # print(div_list)
        # 遍历上面所有的div,找到指定的内容即可
        for div in div_list:
            # 创建item对象 就是我们在items里面定义的类
            item = HuaprojectItem()
            image_url = div.xpath('./div[@class="item_t"]/div[@class="img"]/a/img/@src').extract_first()
            # 处理周半仙图片是以.php结尾的
            if image_url.endswith('.php'):
                image_url = image_url.replace('.php', '.jpg')

            # 拼接图片的全路径
            image_url = 'http://www.xiaohuar.com' + image_url

            name = div.xpath('./div[@class="item_t"]/div[@class="img"]/span[@class="price"]/text()').extract_first()
            school = div.xpath('./div[@class="item_t"]/div[@class="img"]/div[@class="btns"]/a/text()').extract_first()
            like = div.xpath('./div[contains(@class,"item_b")]//em[@class="bold"]/text()').extract_first()
            # 将上面提取的属性保存到对象中
            item['image_url'] = image_url
            item['name'] = name
            item['school'] = school
            item['like'] = like
            # 将该item对象返回
            yield item

        # url = 'http://www.xiaohuar.com/hua/list-1-'
        # page = 0
        # 当处理完第一页的时候,要接着发送请求,处理下一页
        self.page += 1
        if self.page <= 11:
            url = self.url + str(self.page) + '.html'
            # 再次的发送请求,并且指定回调处理函数进行处理对应的请求
            yield scrapy.Request(url=url, callback=self.parse)

4、pipelines.py文件的处理

import json
import os
import urllib.request

class HuaprojectPipeline(object):
    # 重写构造方法,在这打开文件
    def __init__(self):
        # 文件的打开写到这里,仅会执行一次
        self.fp = open('xiaohua.json', 'w', encoding='utf-8')
        
    def open_spider(self, spider):
        pass

    # 在这里处理每一个item
    def process_item(self, item, spider):
        # 将这个对象转化为字典
        obj = dict(item)

        # 将图片下载到本地
        # 获取当前目录的绝对路径
        file_root_path = os.path.dirname(os.path.abspath(__file__))
        # 拼接需要保存的路径
        img_dir_path = os.path.join(file_root_path, 'spiders/images')
        # 判断这个目录是否已经存在,不存在就自动创建
        is_have_img_dir = os.path.exists(img_dir_path)
        if is_have_img_dir:
            pass
        else:
            os.mkdir(img_dir_path)
        # 获取图片后缀名
        suffix = os.path.splitext(obj['image_url'])[-1]
        # 拼接文件名
        filename = obj['like'] + '_' + obj['school'] + '_' +  obj['name'] + suffix
        # 将文件路径和文件名拼接出来文件的全路径
        filepath = os.path.join(img_dir_path, filename)
        # 下载图片
        urllib.request.urlretrieve(obj['image_url'], filepath)

        # 将obj转化为字符串
        string = json.dumps(obj, ensure_ascii=False)
        self.fp.write(string + '\n')
        return item

    # 重写这个方法,在关闭spider的时候将文件资源关闭
    def close_spider(self, spider):
        self.fp.close()

5、最后附上项目地址
git@gitee.com:aeasringnar/xiaohuaproject.git

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐