对于scrapy我还是没有感觉到他的强大 怪我太菜 仍然感觉requests好用

本片基于360图片的爬取 并对深度的爬取 不爬取封面 太lower了

直接进入正题 首先明确360的图片为动态加载 所以毫无疑问你需要访问xhr 由于本人喜欢二次元所以选择了cosplay

基于scrapy 的360图片爬取 item中图片存储多个链接并下载

 下面两个图片为动态加载的第二页于 第三页 这里可以很清楚的看见其js文件 且无传递值 所以基本无反爬 url的规则行极高

其第一页的url为https://image.so.com/zj?ch=beauty&t1=598&sn=0&listtype=new&temp=1 很明显的可以看出他的url规律

url="https://image.so.com/zj?ch=beauty&t1=598&sn={}0&listtype=new&temp=1" {}中的数字即为对应的页数从0开始3为步长

基于scrapy 的360图片爬取 item中图片存储多个链接并下载基于scrapy 的360图片爬取 item中图片存储多个链接并下载

接着分析其内容。其文本格式也不怎么复杂,在list中存储图片的信息请注意cover_imgurl qhimg_thumb_url qhimg_url均为封面图片 只是大小不同不必在意  如果大家只下载其封面的话就不用看了,我想爬的是其所有照片,下面这个网站

基于scrapy 的360图片爬取 item中图片存储多个链接并下载

 

基于scrapy 的360图片爬取 item中图片存储多个链接并下载

而这个网站的链接并不存在于上面那个json文件中 在下图

 

这个网站不是异步加载 url简单但最后的参数才是关键这个参数只能从下图获取基于scrapy 的360图片爬取 item中图片存储多个链接并下载

而这个东西还是异步加载 还需分析

基于scrapy 的360图片爬取 item中图片存储多个链接并下载

其url构成简单也无多余的东西 只有一个id未确认 而id是从最开始的json中提取出来的所以与不是很难 接下来就是找取对于一个cosplay的网页当中其照片的规律

基于scrapy 的360图片爬取 item中图片存储多个链接并下载

这个很简单不做过多的说明

接下来进入代码部分本文采用的是scrapy的 说明均在代码中展示首先是项目结构

基于scrapy 的360图片爬取 item中图片存储多个链接并下载

 

一、items.py

# -*- coding: utf-8 -*-
# Define here the models for your scraped items
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class Pictures360Item(scrapy.Item):
    group_title=scrapy.Field()#标题名    
    id=scrapy.Field()#图片id
    group_pageurl=scrapy.Field()#mycoser网的网址
    worker=scrapy.Field()#拍摄这一组图片的工作人员
    image_urls=scrapy.Field()#这一组图片的url链接 因为谁家拍图拍一张啊

二、

settings.py

BOT_NAME = 'pictures360'

SPIDER_MODULES = ['pictures360.spiders']
NEWSPIDER_MODULE = 'pictures360.spiders'#上面三项均为系统自动定义的值

IMAGES_STORE="./images"#图片存储的位置 若是没有 自动创建 但必不可少

ROBOTSTXT_OBEY = False#robot协议 改成False 使其不遵守robot协议
FEED_EXPORT_ENCODING = 'utf-8'#必须加上 这是显示中文
ITEM_PIPELINES = {
    'pictures360.pipelines.ImagesPipeline': 330,
    'pictures360.pipelines.Pictures360Pipeline': 361,
}#通道函数的执行顺序排列 后面为参数优先级 数越小越先执行 先对图片进行下载 把下载失败的剔除掉 然后再进行文件的写入
#IMAGES_URLS_FIELD="image_urls" 这行代码好像没啥用 在前期搜集资料时好像用到了
SPIDER_MIDDLEWARES = {
   'pictures360.middlewares.Pictures360SpiderMiddleware': 543,
}#这行代码也没啥用 因为没有对middlewares重新定义

三、pictures.py

# -*- coding: utf-8 -*-
import scrapy
import json
from pictures360.items import Pictures360Item
from urllib.parse import urljoin

class PicturesSpider(scrapy.Spider):
    name = 'pictures'
    allowed_domains = ['image.so.com']
    def start_requests(self):#对要爬取的页面进行重新定义 由于是一个规则的url链接所以重新定义                          此函数
        Max=2
        for i in range(Max):
            url="https://image.so.com/zj?ch=beauty&t1=598&sn={}0&listtype=new&temp=1"
            yield scrapy.Request(url.format(i*3),callback=self.parse,dont_filter=True)通过yield进行迭代处理 说白了就是循环处理 而每次处理在上一次的后面 这里请注意callback函数为回调函数 start_requests函数时一个url列表,将每一个url都交给parse函数处理dont_filter默认值为Flase是默认去重 而在迭代爬取中 不更改为Ture会使爬虫框架刚执行就结束

    def parse(self, response):
        lists=json.loads(response.text)#由于链接返回值为json格式 所以转为json
        for everyone in lists["list"]:#对各种数据的提取
            item=Pictures360Item()#实例化items
            item["group_title"]=everyone["group_title"]
            item["id"]=everyone["id"]
            id=everyone["id"]
            url="https://image.so.com/zvj?ch=beauty&t1=598&id={}".format(id)#对url的重新定义
            yield scrapy.Request(url,meta={"key":item},callback=self.middle_page,dont_filter=True)#这里于上面的基本相同 重点在于meta参数 参数的目的在于传递item 由于定义的items的值并不是都在一个网页中 所以要向下传递 而 meta参数是以字典的形式传递的 key值随意 value值为实例化items的值

    def middle_page(self,response):#本函数基本同上 只是对网页的进一步提取
        item=response.meta["key"]#先将item接收
        item["group_pageurl"]=json.loads(response.text)["group_pageurl"]
        url=json.loads(response.text)["group_pageurl"]
        yield  scrapy.Request(url,meta={"key":item},callback=self.finally_page,dont_filter=True)

    def finally_page(self,response):#对最终静态网页的处理
        item=response.meta["key"]
        url="http://www.mycoser.com/"
        lasturls=[]
        item["worker"]=response.css(".text a::text").extract()

        for lasturl in response.css('.center img::attr("layer-src")').extract():
            lasturls.append(urljoin(url,lasturl))#urljoin是网页url的拼接
        item["image_urls"] = lasturls
        yield item#返回item

四、pipelines.py

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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
import json
from scrapy import Request
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline

class Pictures360Pipeline(object):#此函数为项目初始化给的 
    def __init__(self):#初始化一下保存路径
        self.file=open("360.json","w",encoding="utf-8")

    def process_item(self, item, spider):#文件的保存
        content=json.dumps(dict(item),ensure_ascii=False)+"\n"
        self.file.write(content)
        return item

    def close_spider(self,spider):#关闭文件
        self.file.close()

class ImagesPipeline(ImagesPipeline):#由于要保存图片 但是scrapy内置的函数于要求不符所以重写 
    def file_path(self,request,response=None,info=None):#设置保存路径
        url=request.url#提取url链接 这里可以深挖一下 是不是可以提取别的参数
        file_name=url.split("/")[-1]
        return file_name

    def item_completed(self,results,item,info):#对不能下载的图片链接进行剔除 results 与 item info 在下图给出
        image_paths=[x["path"] for ok,x in results if ok] 
        if not image_paths: #根据是否拥有存储地址来判断是否要抛出异常 
            raise DropItem("failed")
        return item

    def get_media_requests(self,item,info): #这里很重要 因为要下载的url为列表 所以要循环后进行迭代
        for i in item["image_urls"]:
            yield Request(i)

 

基于scrapy 的360图片爬取 item中图片存储多个链接并下载

五、begin.py

from scrapy import cmdline
cmdline.execute("scrapy crawl pictures".split())

命令行执行

这样就可以了 

基于scrapy 的360图片爬取 item中图片存储多个链接并下载

如果有任何疑问请滴滴我

相关文章:

  • 2021-08-21
  • 2021-11-30
  • 2021-08-10
  • 2021-06-17
  • 2021-07-01
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-09-24
  • 2021-05-20
  • 2022-12-23
  • 2022-12-23
  • 2021-10-06
  • 2021-11-02
  • 2021-04-06
相关资源
相似解决方案