本文共 3840 字,大约阅读时间需要 12 分钟。
使用的requests库爬取斗图网的最新表情包,爬取的过程就不细说了,原来的爬虫爬取的表情包是直接存放在硬盘上的,这一版改为存放在MySQL数据库中。原来的爬虫网址如下:。详细的爬虫解释都在原帖,这次主要是讲数据库存取图片,并与爬虫相结合。
首先,需要明确几点,数据库的存取问题可以分为这么几个问题,1,存什么,要存进数据库的文件也就是数据源在哪?2.存放的必要性思考,3,数据库是存放数据的,那么数据存放在数据库哪里?4,存放的数据的形式。
存取是一对动作,有存就有取。
先说第一个问题,存什么?存图片!这是现在要研究的问题,图片哪来?以往所保存的,自己手动下载收集的,从图片网站搜索然后手动下载的,爬虫从图片网站爬取的,使用工具自动生成的图片(比如,视频分析后自动截屏),手机相机所拍摄的图片等等来源,那么图片有几种属性是所需要关注的,图片的名称,图片的大小,图片的格式是应该关注的。在这的来源是爬虫所爬取的图片。
第二个问题,图片存放在数据库中的好处有几点,第一,便于管理,第二,可以远程方便的查看或者下载图片,第三,可以方便的将图片展示在自己的网站之中,数据的获取会更便捷。第四,只要数据库是安全的,那么数据也就不会泄露或者损坏。
第三个问题,数据库既然都称为库了,那么毫无疑问,仓库是会有许多的单独的房间的,同样,只能存放在一个指定的库中的一张单独表内、
第四个问题,存放的数据形式,根据图片的特征,图片的大小通常在十几k到几兆,并且是以二进制数据的形式存放在表内,因此需要使用BLOB类型的字段,该字段用于存储二进制数据,四种blob字段,分别为
因此,使用mdeiumblob基本可以满足需要了。
下面,开始存取图片的演示:
import MySQLdbclass Save_Picture(): def __init__(self): self.conn=MySQLdb.connect(host='数据库IP',user='root',passwd='数据库',db='要使用的库名')#初始化数据库连接 def setup(self): cursor = self.conn.cursor()#建立游标 cursor.execute(""" #执行表创建语句 CREATE TABLE IF NOT EXISTS `picture` ( #表名是picutre,如果不存在建立,存在忽略 `ID` int(11) NOT NULL auto_increment, #表内主键,自增ID,int类型 `PicData` longblob, #表内列名:PicData,longblob类型, PRIMARY KEY (`ID`) #id为主键 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; #使用innodb引擎,默认字符集为utf8,从序号1开始自增 """) def save_pic(self): f=open('c:\\1445235.jpg','rb')#打开硬盘上的图片文件,只读二进制模式打开,读取硬盘文件 b=f.read()#存入内存,变量名为b f.close()#关闭二进制流 cursor=self.conn.cursor()#开启游标 sql='insert INTO picture(PicData) VALUES (%s)'#sql语句。 args=(MySQLdb.Binary(b),)#配合sql语句的参数,也就是要存的图片的二进制流。#这里一定要注意,前面定义的表内有两个列,因此,参数也要两个,在这是是用了逗号,后面的id省略了#逗号,逗号,逗号,逗号,必须有,两个列,id这个列是自增的主键不用写,逗号后其实是有东西的。#这个地方是个坑,坑了我一个多小时,定义了多少个列,参数写多少个!!!切记!!!! cursor.execute(sql,args)#执行sql语句 self.conn.commit()#必须要有的一步,正式写入数据库。这步是提交数据库,必须有!!! cursor.close()#关闭连接 def readpic(self):#读取数据库内的数据,没什么好说的,只需要记住写入硬盘文件时是wb,写入二进制模式。。 cursor=self.conn.cursor() cursor.execute('select PicData from picture order by id desc limit 1') d=cursor.fetchone()[0] cursor.close() f=open('c:\\aa.jpg','wb') f.write(d) f.close()if __name__=='__main__': test=Save_Picture()#类方法的调用 test.setup() test.save_pic() #test.readpic()
根据以上的代码,改进了下爬虫,下面是爬虫代码:
import requestsimport reimport timeimport MySQLdburl='https://www.doutula.com/photo/list/?page='headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/53" "7.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36" }for i in range(0,2): thisurl=url+str(i+1) data=requests.get(url=thisurl,headers=headers) data.encoding='utf-8' print(data) print('开始爬取第',str(i+1),'ye') pat='data-backup="(.*?)">' picurl=re.compile(pat,re.S).findall(data.text) #pat1='' print(picurl) for j in range(0,len(picurl)): #print(picurl[j]) pic=requests.get(picurl[j]).content conn=MySQLdb.connect(host='***',user='root',passwd='***',db='库名') conn.ping(True) cursor=conn.cursor() cursor.execute('insert into picture(PicData) values (%s)',(MySQLdb.Binary(pic),)) conn.commit() cursor.close()#只需要注意一下,关闭数据库是在第二个for循环完毕后,不要在循环内关闭,否则很耗费时间和cpu#建表参考上面的代码,或者使用下面的,建表前要先建库哦!!!!!!!!!! CREATE TABLE IF NOT EXISTS `picture` ( `ID` int(11) NOT NULL auto_increment, `PicData` longblob, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
补充说明:执行sql语句的那么几步,一定要注意,两个列名,对应的参数也就是两个,那么,参数必须是元组的形式,并且第二个id参数需要省略,所以使用逗号表示省略。cursor.execute('insert into picture(PicData) values (%s)',(MySQLdb.Binary(pic),))
这句末尾如果没有逗号,那么会报错TypeError: not all arguments converted during string formatting,表示参数给多了。
转载地址:http://ulkr.baihongyu.com/