scrapy爬取百度图片遇见的防盗链问题

刚学的爬虫,之前都是学的爬取静态网页图片,这次尝试爬取百度的图片,用xpath解析网页获取的都是空列表,后来查阅资料才知道百度图片的网页是动态的,采用的都是Ajax+JSON机制。

网页原始数据是没有图片的,通过运行JavaScript,把图片数据插入到网页的HTML标签中。所以我们在开发者工具中虽然能看到这个HTML标签,但是网页的原始数据其实没有这个标签,它只在运行时加载和渲染。真实的图片信息被打包放在JSON文件当中,所以真正要解析的是JSON文件。

百度搜索柯南

在这里插入图片描述

点击Network–XHR,在往下滑动滚动条时,会连续出现名为acjson的请求,再点击Preview,我们看到这是一条JSON数据,点开data,我们看到这里面有30条数据,每一条都对应着一张图片。

在这里插入图片描述

图片的url地址就在data里面的middleURL中,点击data,然后随便点一条数据,比如0,然后往下面拉,会看到如下图所示结果

在这里插入图片描述

但是我们要获取的图片的url地址在json数据里,json文件的url在Headers下的Request URL中,并且我们会发现所有的json文件的url只有pn字段保持以30为步长递增,其余不变

在这里插入图片描述
在这里插入图片描述

编写我们的spider,因为一个json数据只有30张图片,所以我们要重写start_urls,下图代码的url就是上图中的Request URL,需要将其pn改变,所以用for循环

# -*- coding: utf-8 -*-
import scrapy
from meizi.items import  MeiziItem
import json

class MeiziSpiderSpider(scrapy.Spider):
    name = 'meizi_spider'
    allowed_domains = ['image.baidu.com']


    #重写start_urls,按照我们自己的需求
    def start_requests(self):
        for i in range(30,120,30):
            url="https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord=%E6%9F%AF%E5%8D%97&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=&latest=&copyright=&word=%E6%9F%AF%E5%8D%97&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn={}&rn=30".format(i)
            # 交给调度器
            yield scrapy.Request(url, callback=self.parse)


    def parse(self, response):
        imgs=json.loads(response.body).get("data")     #json文件是一个字典
        # print(imgs),imgs是一个列表
        for img in imgs:
            item=MeiziItem()
            item['image_urls']=[img['middleURL']]
            print(img['middleURL'])
            yield(item)







items文件

import scrapy


class MeiziItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()

    #image_urls是scrapy下载图片时自带的属性,不可以改变,如果要该成自定义的
    #比如  URL=scrapy.Field()
    #需要在settings文件中添加  IMAGES_URLS_FIELD='URL'  这个表示图片的url属性是URL
    image_urls=scrapy.Field()

settings文件,!!!注意这里为了防止防盗链,在DEFAULT_REQUEST_HEADERS里面一定要添加referer属性,否则下载下来的图片会显示图片失败!!!

BOT_NAME = 'meizi'

SPIDER_MODULES = ['meizi.spiders']
NEWSPIDER_MODULE = 'meizi.spiders'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

DEFAULT_REQUEST_HEADERS = {
  "referer":"http://image.baidu.com/search/",
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
  'User-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
}

ITEM_PIPELINES = {
   # 'meizi.pipelines.MeiziPipeline': 300,
    'scrapy.pipelines.images.ImagesPipeline':1
}

IMAGES_STORE = "E:/meizi/"
# IMAGES_URLS_FIELD='URL'
# LOG_FILE="scrapy.log"    将爬取的状态保存到scrapy.log里面

pipelines文件,因为这里使用了scrapy自带的下载图片功能,所以pipelines文件就不用修改了,只需要在settings文件中将 ‘meizi.pipelines.MeiziPipeline’: 300这句注释掉,添加一句’scrapy.pipelines.images.ImagesPipeline’:1

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


class MeiziPipeline:
    def process_item(self, item, spider):
        return item

最后执行下start文件

from scrapy import cmdline

cmdline.execute("scrapy crawl meizi_spider".split())

爬取结果

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值