python爬取微博图片数据存到Mysql中遇到的各种坑\ python Mysql存储图片

  

本人长期出售超大量微博数据,旅游网站评论数据,并提供各种指定数据爬取服务,消息发送到YuboonaZhang@Yahoo.com。同时欢迎加入社交媒体数据交流群:99918768

  

前言

  

? ?由于硬件等各种原因需要把大概170多万2 t左右的微博图片数据存到Mysql中。之前存微博数据一直用的非关系型数据库mongodb,由于对Mysql的各种不熟悉,踩了无数坑,来来回回改了3天才完成。

  

挖的坑填坑之旅

  

<>强建表

  

存数据的时候首先需要设计数据库,我准备设计了3个表

  

微博表:[id、用户id blog_text lat,液化天然气,created_time,储备)? ?<强> pkey: id

  

图片表:(md5、pic_url pic_bin, exif,储备)? ?<强> pkey: md5

  

关系表:[id、md5、储备]? ?<强> pkey: (id、md5) ?fkey:(id、微博表id) ?(md5,图片表md5)

  

? ?建表的时候别的问题都还好,主要是pic_bin的类型和blog_text的类型有很大的问题,首先是pic_bin的类型,开始设置的为<强> BLOB 强劲,但是运行之后发现团最大只能存1 m的数据,并不能满足微博图片的存储,后改成<强> MEDIUMBLOB (16美元)基本能够满足要求了。再后来就是blog_text,我遇到的第一个大坑

  

? ?开始的时候很自然的设置blog_text的类型为文本,但跑起来发现有些数据存不进的去,会报错,经筛查发现是有些微博文本中包含了emoji表情……随后找了很多资料发现是因为utf8下文字是三字节,但是emoji是四字节,需要将编码改成utf8mb4然。而我在mac上整mysql的配置文件报各种奇葩错误,一怒之下把<强> 文本改成了<强> BLOB 强,就好了。因为本地是mac,我要连接到远程的一台Windows上才能通过那个窗户连接到群晖的mysql上……本地配置改了也白改。

  

<>强存图片

  

? ?然后这就是一个<强> 大坑! ! ! 由于我使用的python3,所以读取图片得到的二进制的结果前面会有一个b”,表示字节,正是由于这个b”导致sql语句拼接的时候这个<强> b后面的单引号会和sql语句的引号结合强,导致后面的二进制没有在引号里面出错!二进制编码又不像字符串可以对字符转义,试了好多方法都不行!最后没有办法使用base64对二进制进行加密转化成字符串,存到数据库中,然后要用时的时候再解密。

  
 <=坝镅詐ython代码类> pic_bin=str (base64.b64encode (pic_bin))(2): 1)  
  

<>强改配置文件

  

? ?由于使用Python多进程,一个小时8 g数据量,图片数据比较大,发包的时候回超过mysql的默认限制,出现mysql服务器已经消失,这个时候要改配置文件,在配置文件中参数

  

<强> max_allowed_packet=600
<强> wait_timeout=60000

  

<>强期间失去了连接到Mysql服务器查询

  

? ?程序跑着跑着总会出现这个错误,一直找原因,试了各种办法看了好多资料,一直都是错误。实在不知道什么原因了…后来一想,我管他什么原因,失去连接之后重新连接就行了。使用conn.Ping(真正的)判断是否连接mysql成功。如果失去连接就重新连接就行了!最后解决了这个问题

  

<>强代码实现

  
 <代码类="语言python "> # !/usr/bin/env python
  # - * -编码:utf - 8 - *
  #由Baoyi 2017/10/16
  多处理。池进口池
  
  进口pymysql
  进口的要求
  进口json
  进口exifread
  从io进口BytesIO
  进口configparser
  进口hashlib
  导入日志
  进口base64
  
  #配置日志=logging.WARNING logging.basicConfig(水平,
  格式=' % (asctime) %(文件名)年代[:% (lineno) d] % (levelname) %(消息)年代',
  datefmt=' %, % d % b % Y % H: % M: % S的,
  文件名=' weibo.log ',
  filemode=' w ')
  
  cf=configparser.ConfigParser ()
  cf.read (“ConfigParser.conf”)
  
  #读取配置mysql
  db_host=cf.get (“mysql”、“db_host”)
  db_port=cf.getint (“mysql”、“db_port”)
  db_user=cf.get (“mysql”、“db_user”)
  db_pass=cf.get (“mysql”、“db_pass”)
  db=cf.get (“mysql”、“数据库”)
  
  #创建连接
  康涅狄格州=pymysql。连接(主机=db_host、用户=db_user passwd=db_pass db=db,端口=db_port charset=use utf8)
  #获取游标
  光标=conn.cursor ()
  
  #创建insert_sql
  insert_blog_sql=(
  “插入忽视博客(用户id, id、blog_text lat,液化天然气,created_time)值(“{uid}”,“{id}”,“{blog_text}”,“{lat}”,“{液化天然气}”,“{created_time}”)”
  )
  
  insert_pic_sql=(
  “忽略插入图片(pic_url pic_bin, md5, exif)值({pic_url}, {pic_bin}, {md5}, {exif})”
  )
  
  insert_relationship_sql=(
  “插入忽略关系(id、md5)值({id}, {md5})”
  )
  
  uid=[]
  
  (“开放。/数据/final_id。txt”、“r”)作为f:
  因为我在f.readlines ():
  uid.append (i.strip (“\ r \ n”))
  
  #处理图片数据
  def handle_pic (pic_url):
  large_pic_url=pic_url。替换(“缩略图”,“大”)
  large_bin=requests.get (large_pic_url)
  返回large_bin.content
  
  def get_poiid_info (uid):
  试一试:
  url=' https://api.weibo.com/2/statuses/user_timeline.json '
  负荷={
  “access_token”:“xxxxxxxxxx”,
  “uid”: uid,
  “数”:100年,
  “功能”:2
  “trim_user”: 1
  }
  get_info=请求。get (url=url, params=负载,超时=(10,10))
  如果get_info。status_code !=200:
  logging.warning (ConnectionError)
  通过
  info_json=json.loads (get_info.content)
  info_json (“uid”)=uid
  状态=info_json(的状态)
  #处理筛选微博数据
  状态的状态:
  id=状态(“idstr”)
  如果状态(“地理”)不是没有:
  lat=状态[“地理”]['协调'][0]
  液化天然气=状态(“地理”)(“坐标”)[1]
  pic_urls=状态(“pic_urls”)
  
  #判断是否在北京
  如果(115.7 & lt;液化天然气& lt;117.4)和(39.4 & lt;lat & lt;41.6):
  #若在北京,插入博客数据进库
  blog_text=状态(“文本”)。替换(“\”、\ \”)
  created_time=状态(“created_at”)
  试一试:
  cursor.execute (
  insert_blog_sql。格式(uid=uid, id=id, blog_text=blog_text lat=lat,液化天然气液化天然气,
  created_time=created_time))
  pymysql.err除外。OperationalError e_blog:
  logging.warning (e_blog.args [1])
  通过
  
  # conn.commit ()
  #处理图片
  在pic_urls pic_url:
  #获取原图片二进制数据
  pic_bin=handle_pic (pic_url [' thumbnail_pic '])
  
  #读取exif数据
  pic_file=BytesIO (pic_bin) #将二进制数据转化成文件对象便于读取exif数据信息和生成MD5
  标签1=exifread。=False process_file (pic_file细节,严格=True)
  标签={}
  关键,价值tag1.items ():
  如果关键不在(
  “JPEGThumbnail”、“TIFFThumbnail”,“文件名”,
  EXIF MakerNote): #去除四个不必要的EXIF属性,简化信息量
  标签(关键)=str(值)=json.dumps标签(标签)#转储为json类型此标记即为exif的json数据
  #生成MD5
  MD5=hashlib.md5 (pic_file.read ()) .hexdigest ()
  #首先把二进制图片用base64转成字符串之后再存
  试一试:
  cursor.execute (
  insert_pic_sql.format (pic_url=pic_url [' thumbnail_pic ']。null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null

python爬取微博图片数据存到Mysql中遇到的各种坑\ python Mysql存储图片