【Scrapy-03】布隆过滤器、存储数据库以及其他一些图片爬取的技巧

Python3+Windows的环境,使用布隆过滤器确实不是一个很明智的选择,因为要么现成的模块不支持Windows平台,要么就是只支持Python2,要么就是对文件操作的支持不理想。经过不懈努力,找到一个叫做bloom_filter的。

——布隆过滤器的使用,使用效果确实不错,先自己新建一个文件,然后每次打开,检查是否存在,不存在就添加,存在的话就不错什么处理了。这里面我做了两个布隆过滤的文件,并且做了两个判断,第一次是判断这个要下载的图片的url是否已经存在(就是是否已经下载过了),如果下载过了,那就忽略,如果没有下载过,那么就下载;下载之后,对下载的文件进行sha1的处理,然后拿这个sha1去比对是否已经存在,这是防止在不同网站下载了同一张图片,如果不存在,说明这张图片是唯一的,但是不能保证这个图片的图像是没有重复的,因为只要修改了一点点的图片属性或信息,那么他们也会属于不同的图片。

——其次,是连接数据库的一些操作,这里用的是pymysql,记得再初始化里面连接数据库,在close_spider方法中关闭连接。

——中间的一些过程就是,判断路径是否存在,不存在就创建,存在就如何如何。这里面用了年月日的目录来存储下载的图片,是为了保证图片存储相对合理一些,而不是放在一个大文件夹中。

——这里的sha1的处理用的是hashlib的库。

——这里对同一组图片会有一个统一的标识。

——对图片进行了重命名,防止出现重复的时候它会自己命名。

——在数据库中的存储可以看出来,是将图片储存的路径dir和名称name是分开来的,这是为了防止以后图片的移动。

import pymysql
import urllib.request
import uuid
import datetime
import os
from bloom_filter import BloomFilter
import hashlib

class DesignhubPipeline(object):
    def __init__(self):
        self.conn = pymysql.connect(host="127.0.0.1", user="root", password="root", db="dlimg", charset='utf8mb4')
        self.bf_urls = BloomFilter(max_elements=10000000,error_rate=0.001,filename="C:/Users/Eric/Downloads/dlimg/bloomfilter/img_urls.bf")
        self.bf_sha1s = BloomFilter(max_elements=10000000,error_rate=0.001,filename="C:/Users/Eric/Downloads/dlimg/bloomfilter/img_sha1s.bf")

    def process_item(self, item, spider):
        if len(item["img_urls"]) == 0:
            return item
        for img_url in item["img_urls"]:
            # check out whether this img_url exists
            if img_url not in self.bf_urls:
                self.bf_urls.add(img_url)
                try:
                    base_dir = "C:\\Users\\Eric\\Downloads\\dlimg\\"
                    today = datetime.datetime.today().isoformat()
                    img_dir = base_dir + today[:4] + "\\" + today[5:7] + "\\" + today[8:10] + "\\"
                    if not os.path.exists(img_dir):
                        # create dir
                        os.makedirs(img_dir)
                    img_name = str(uuid.uuid1()) + ".jpg"
                    img_path = img_dir.replace("\\", "/") + img_name
                    opener = urllib.request.build_opener()
                    opener.addheaders = [('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'),
                                         ('Accept','text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'),
                                         ('Refer','https://www.yatzer.com/'),
                                         ('Cache-Control','no-cache')]
                    urllib.request.install_opener(opener)
                    urllib.request.urlretrieve(img_url, img_path)
                    # check out whether this img_file exists
                    with open(img_path, "rb") as f:
                        sha1Obj = hashlib.sha1()
                        sha1Obj.update(f.read())
                        hashRs = sha1Obj.hexdigest()
                        if hashRs in self.bf_sha1s:
                            # print("删除文件")
                            os.remove(img_path)
                        else:
                            self.bf_sha1s.add(hashRs)
                            sql = "insert into `dl_img`(`IMG_ID`,`IMG_DIR`,`IMG_NAME`,`GROUP_ID`,`SOURCE_URL`,`CREATE_DATE`) values(%s, %s, %s, %s,%s, %s)"
                            with self.conn.cursor() as cursor:
                                cursor.execute(sql, (str(uuid.uuid1()), img_dir.replace("\\", "/"), img_name, str(item["group_id"]), item["source_url"], datetime.datetime.now()))
                                self.conn.commit()
                except Exception as e:
                    pass
        return item

    def close_spider(self, spider):
        self.conn.cursor().close()
        self.conn.close()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值