利用scrapy框架爬取风景图片网,以及利用scrapy的基本步骤

注意:此处为主代码,,还需要设置一些,具体请参考下面基本步骤的内容
# -*- coding: utf-8 -*-
# -*- coding:utf-8 -*-
#爬虫框架:Scrapy   PySpider    Selenium(其中1,3必须会)
#其中Selenium自动测试的一个框架
#打开项目步骤(项目在桌面):看图片
#如果文件夹下存在__init__文件,,证明是一个包,删除就变成一个普通的文件夹
#.............仍是爬取天堂图片网..................
#在终端创建项目(看老师发的图片)  scrapy startproject IvskySpider
#创建文件,不在终端,在pycharm终端,,看图片,

#打开文件
#注意:爬虫名称必须唯一,一般不改
#2.域名如果不存在,就不会爬取
#3.网址一般需要手动重新设置,可以存放多个网址
import scrapy
import os
import requests
#
#一个点(.)表示当前文件所在文件夹,两个点表示文件夹的文件夹
from ..items import ImgInfoItem

#此处不用导入,因为scrapy框架自带一种解析方式,基于lxml
#from lxml import etree


class IvskySpider(scrapy.Spider):
    name = 'ivsky'
    allowed_domains = ['ivsky.com']
    start_urls = ['http://www.ivsky.com/tupian/ziranfengguang/']

    def parse(self, response):
        #这里的response跟之前的不是太一样,没有content属性
        # print(response.text)

        #常规写法,调用函数
        # self.parse_big_category(response)

        #框架中的写法,用yield调用函数节省时间
        """
        参数一:url,爬取的网址
        参数2:callback回调,当网页下载好之后传给谁去解析
        参数三:method,默认get
        hesders
        cookies
        meta
        """
        #解析大分类
        yield scrapy.Request(
            url=response.url,
            #注意:此处不带圆括号
            callback=self.parse_big_category,
            #scrapy会自动过滤已经爬过的地址,因此设置为true,表示不过滤
            dont_filter=True,
        )

    #解析大分类
    def parse_big_category(self,response):
        """
        解析网页大分类
        :param response:
        :return:
        """
        #以下三种解析方式都可以用,但是推荐使用xpath
        # response.selector.xpath()
        #以上一句简写
        big_a_list = response.xpath("//ul[@class='tpmenu']/li/a")
        for big_a in big_a_list[1:]:
            #extract_first()将列表中的元素转换成字符串并且取第0个,如果取不到,就返回默认值
            big_title = big_a.xpath("text("
                                    ")").extract_first("没有标题")
            big_href = big_a.xpath("@href").extract_first("没有地址")
            big_href="http://www.ivsky.com"+big_href
            #在大分类中解析小分类
            yield scrapy.Request(
                url=big_href,
                callback=self.parse_small_category,
                #meta负责传递数据,参数类型一般是个字典
                meta={
                    "big_title":big_title
                },
                dont_filter = True
            )
            # print(big_title,big_href)
        # response.selector.css()
        # response.selector.re()

    #解析小分类
    def parse_small_category(self,response):
        """
        解析网页小分类
        :param response:
        :return:
        """
        #拿大分类标题,meta是response的属性
        # big_title = response.meta.get("big_title")

        small_a_list = response.xpath("//div["
                       "@class='sline']/div/a")
        for small_a in small_a_list:
            small_title = small_a.xpath("text("
                                    ")").extract_first(
                "没有标题")
            #在原有基础上增加一个字段   添加小标题
            response.meta['small_title'] = small_title

            small_href = small_a.xpath(
                "@href").extract_first("没有地址")
            small_href = "http://www.ivsky.com" +small_href
            # print(small_title,small_href)
            yield scrapy.Request(
                url=small_href,
                callback=self.parse_img_list,
                # meta={
                #     "big_title": big_title,
                #     "small_title":small_title
                # }
                meta=response.meta,
                dont_filter=True
            )

    #解析图片列表
    def parse_img_list(self,response):
        """
        解析图片缩略图
        :param response:
        :return:
        """
        img_a_list = response.xpath("//ul[@class='pli']/li/div/a")
        for img_a in img_a_list:
            detail_href = img_a.xpath(
                "@href").extract_first("没有详情地址")
            detail_href="http://www.ivsky.com"+detail_href
            thumb_src = img_a.xpath(
                "img/@src").extract_first("没有图片地址")
            thumb_alt = img_a.xpath(
                "img/@alt").extract_first(
                "没有图片名称")
            response.meta['thumb_src'] = thumb_src
            response.meta['thumb_alt'] = thumb_alt
            # print(thumb_alt,thumb_src)
            yield scrapy.Request(
                url=detail_href,
                callback=self.parse_img_detail,
                meta=response.meta,
                dont_filter=True
            )


    # 解析大图
    def parse_img_detail(self, response):
        """
        解析图片详情
        :param response:
        :return:
        """
        big_title = response.meta.get(
            "big_title").strip()
        small_title = response.meta.get(
            "small_title").strip()
        thumb_src = response.meta.get("thumb_src").strip()
        thumb_alt = response.meta.get("thumb_alt").strip()
        img_detail_src = response.xpath("//img[@id='imgis']/@src").extract_first("没有图片详情地址")
        # print(img_detail_src)
        path = "total/"+big_title+"/"+small_title+"/"+thumb_alt
        if not os.path.exists(path):
            os.makedirs(path)
        picture_name = thumb_src.split('/')[-1]
        thumb_name = "缩略图"+picture_name
        detail_name = "高清图"+picture_name
        # 创建对象
        item = ImgInfoItem()
        item['big_title']=big_title
        item['small_title']=small_title
        item['thumb_src']=thumb_src
        item['thumb_alt']=thumb_alt
        item['img_detail_src']=img_detail_src
        item['path']=path
        #yield类似于return,return后面的代码不执行,但是yield后面的会返回
        yield item
        with open(path+"/"+thumb_name,"wb") as f:
            img_response = requests.get(thumb_src)
            f.write(img_response.content)
        with open(path+"/"+detail_name,"wb") as f:
            img_response = requests.get(img_detail_src)
            f.write(img_response.content)

"""
进程:进程之间数据是独立的
线程:生活在进程里面,一个进程里面会包含多个线程,一个进程     相当于一个人,一个线程相当于一个脑子,所以如果想让      你个进程同时做多件事,需要开多个线程.
    默认线程只有一个,,叫做主线程;
    一个线程每次只能做一件事,例如:迅雷能同时下载任        务量为1;多个线程可以"同时"做多件事,(同时代表感觉      是同时 ),例如:迅雷同时下载任务量为5,可以提高效率.
    注意:线程不是越多越好,例如:火车站卖票,窗口越多,速度        越快,成本越高
    注意:scrapy框架默认用的是多线程
    注意:python没有多线程
协程:主要负责协助线程的资源切换
"""

"""
scrapy默认支持四种数据格式,分别是: .json .csv 
操作:scrapy crawl 爬虫名称 -o 文件名
"""

基本步骤:

在利用scrapy框架进行爬虫时,若通过抓包工具获取的User-Agent数据中含有scrapy,证明是爬虫


                 scrapy的基本用法:
1. 通过命令创建项目
scrapy startproject 项目名称


2. 用pycharm打开项目


3. 通过命令创建爬虫
scrapy genspider 爬虫名称 域名


4. 配置settings(这三个是必须设置的)
robots_obey=False
Download_delay=0.5
Cookie_enable=False


5. 自定义UserAgentMiddleWare


可以直接粘现成的
(1.点开External Libraries-->site-packages-->scrapy-->downloadermiddlewares-->useragent全部复制,
2.粘贴到middlewares文件中,
3.在middlewares文件中需要导入包from fake_useragent import UserAgent
4.修改UserAgentMiddleWare类中的部分内容
)
或者自己通过研究源码实现


6. 开始解析数据
1) 先大致规划一下需要几个函数
2) 函数1跳转到函数2使用 yield scrapy.Request(url,callback,meta,dont_filter)


7. 将数据封装到items,记得yield item


8. 自定义pipelines将数据存储到数据库/文件中






注意:第五步的修改UserAgentMiddleWare类中的部分内容,具体修改如下:


class UserAgentMiddleware(object):
    """This middleware allows spiders to override the user_agent"""


    def __init__(self):
        self.user_agent = UserAgent()


    @classmethod
    #加载配置文件
    def from_crawler(cls, crawler):
        #不用读配置
        o = cls()
        # crawler.signals.connect(o.spider_opened, signal=signals.spider_opened)
        return o


    #该函数不能删,否则会报错
    def spider_opened(self, spider):
        # self.user_agent = getattr(spider, 'user_agent', self.user_agent)
        pass


    #请求处理
    def process_request(self, request, spider):
        if self.user_agent:
            #b是什么二进制(不全,没听清)
            request.headers.setdefault(
                b'User-Agent',
                self.user_agent.random)


你可能感兴趣的:(利用scrapy框架爬取风景图片网,以及利用scrapy的基本步骤)