scrapy框架实现百度图片爬虫

scrapy框架实现百度图片爬虫


这是我个人获取搜索引擎图片的爬虫思路,还有很多待完善的地方
此程序的环境为windows + pycharm + python3.6 + scrapy

思路:百度图片加载是基于ajax数据加载的,图片的url都藏在后台发送的json文件中,所以需要在开发者模式xhr中,找到对应的json请求,然后构造url发送即可得到返回的json文件,然后用正则表达式提取出图片的url,然后用scrapy框架构造爬虫,下载速度非常快,难度也不大。


构造url时,如果搜索内容有中文,可以先单独在终端导入 from urllib.parse import quote
name = "搜索内容"
newName = quote(name) 
print(newName)
即可将中文生成相应的url格式
如中文'赵丽颖''%E8%B5%B5%E4%B8%BD%E9%A2%96'
将爬虫url中的word=后面的内容替换就行

爬虫函数

# -*- coding: utf-8 -*-
import re
import scrapy
from baidu.items import BaiduItem


class DuduSpider(scrapy.Spider):
    # 爬虫名
    name = 'dudu'
    # 爬虫允许的爬取域名范围,最好根据你所要爬取的网站来确定,不能乱写,否则会搜索不到内容,使爬虫不受控制
    allowed_domains = ['image.baidu.com']
    #构建url的起始值offset,具体由网页分析后确定
    offset = 90
    #此处url的'https://'一定要写,不然会报错,而且不容易找出
    url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&word=Tara&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&pn='
    #起始url,列表内字符串的拼接
    start_urls = [url + str(offset)]

    def parse(self, response):
        #使用scrapy shell 返回的内容为json格式,正则匹配出图片链接并提取
        pattern = re.compile(r'"middleURL":"(.*?)",', re.S)
        #此datas返回的是一个正则表达式列表,可迭代取出里面的url
        datas = re.findall(pattern, response.text)
        for data in datas:
            #实例化item
            item = BaiduItem()
            # print("图片链接是:", data)
            item['imageLink'] = data
            #生成器,返回给pipelineItem文件
            # 由一个url获取一个图片的url列表,列表内有若干个图片链接url,依次获取发送图片链接的url,直至发送完,跳出循环
            yield item
        #跳出循环后offset自增30(网页决定)
        self.offset += 30
        #调用此生成器,并发送下一个网页url,回调函数调用self.parse自身,再次循环处理列表中的图片链接url,循环往复获取图片
        yield scrapy.Request(self.url + str(self.offset), callback=self.parse)

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 scrapy

from scrapy.exceptions import DropItem
from scrapy.utils.project import get_project_settings
from scrapy.pipelines.images import ImagesPipeline


class BaiduPipeline(ImagesPipeline):
    #使用settings.py中的设置
    IMAGES_STORE = get_project_settings().get('IMAGES_STORE')

    # 此函数的第一个对象request就是当前下载对应的scrapy.Request对象,这个方法永汉返回保存的文件名,将图片链接的最后一部分党文文件名,确保不会重复
    def file_path(self, request, response=None, info=None):
        url = request.url
        file_name = url.split('/')[-1]
        return file_name

    # 第一个item对象是爬取生成的Item对象,可以将他的url字段取出来,直接生成scrapy.Request对象,此Request加入到调度队列,等待被调度,然后执行下载
    def get_media_requests(self, item, info):
        image_url = item["imageLink"]
        yield scrapy.Request(image_url)

    # 这是单个Item完成下载时的处理方法,各种原因,并不是每张图片都会下载成功,此方法可以剔除下载失败的图片
    # result是该Item对应的下载结果,是一个列表形式,列表每个元素是一个元组,其中包含了下载成功与失败的信息,这里遍历下载结果,找出所有下载成功的列表,如果列表为空,那么此Item对应的图片链接下载失败,随即跑出异常DropItem,该Item忽略,否则返回Item,该Item有效
    def item_completed(self, result, item, info):
        image_path = [x["path"] for ok, x in result if ok]
        if not image_path:
            raise DropItem('Image Dowload Failed')
        return item

在settings.py文件中加上这一行,即保存图片的文件夹,我这里是保存在当前目录下的images文件夹

IMAGES_STORE = "./images"

没有更多推荐了,返回首页