Python 爬取表情包并保存在数据库中(以往的爬虫改进)
使用的requests库爬取斗图网的最新表情包,爬取的过程就不细说了,原来的爬虫爬取的表情包是直接存放在硬盘上的,这一版改为存放在MySQL数据库中。原来的爬虫网址如下:javascript:void(0)。详细的爬虫解释都在原帖,这次主要是讲数据库存取图片,并与爬虫相结合。
首先,需要明确几点,数据库的存取问题可以分为这么几个问题,1,存什么,要存进数据库的文件也就是数据源在哪?2.存放的必要性思考,3,数据库是存放数据的,那么数据存放在数据库哪里?4,存放的数据的形式。
存取是一对动作,有存就有取。
先说第一个问题,存什么?存图片!这是现在要研究的问题,图片哪来?以往所保存的,自己手动下载收集的,从图片网站搜索然后手动下载的,爬虫从图片网站爬取的,使用工具自动生成的图片(比如,视频分析后自动截屏),手机相机所拍摄的图片等等来源,那么图片有几种属性是所需要关注的,图片的名称,图片的大小,图片的格式是应该关注的。在这的来源是爬虫所爬取的图片。
第二个问题,图片存放在数据库中的好处有几点,第一,便于管理,第二,可以远程方便的查看或者下载图片,第三,可以方便的将图片展示在自己的网站之中,数据的获取会更便捷。第四,只要数据库是安全的,那么数据也就不会泄露或者损坏。
第三个问题,数据库既然都称为库了,那么毫无疑问,仓库是会有许多的单独的房间的,同样,只能存放在一个指定的库中的一张单独表内、
第四个问题,存放的数据形式,根据图片的特征,图片的大小通常在十几k到几兆,并且是以二进制数据的形式存放在表内,因此需要使用BLOB类型的字段,该字段用于存储二进制数据,四种blob字段,分别为
- TinyBlob 最大 255
- Blob 最大 65K
- MediumBlob 最大16M
- LongBlob 最大 4G
因此,使用mdeiumblob基本可以满足需要了。
下面,开始存取图片的演示:
import MySQLdb
class 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 requests
import re
import time
import MySQLdb
url='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='<p style="display: none">(.*?)</p>'
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,表示参数给多了。