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

前言

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

挖坑填坑之旅

建表

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

微博表:[id, userid, blog_text, lat, lng, created_time, reserve]   pkey: id

图片表:[md5, pic_url, pic_bin, exif, reserve]   pkey: md5

关系表:[id, md5, reserve]   pkey: (id, md5)   fkey: (id, 微博表id)  (md5, 图片表md5)

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

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

存图片

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

pic_bin = str(base64.b64encode(pic_bin))[2:-1]

改配置文件

  由于使用Python多进程,一个小时8G数据量,图片数据比较大,发包的时候回超过mysql的默认限制,出现Mysql server has gone away, 这个时候要改配置文件,在配置文件中参数

max_allowed_packet = 600M
wait_timeout = 60000

Lost connection to Mysql server during query

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

代码实现

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created by Baoyi on 2017/10/16
from multiprocessing.pool import Poolimport pymysql
import requests
import json
import exifread
from io import BytesIO
import configparser
import hashlib
import logging
import base64# 配置logging
logging.basicConfig(level=logging.WARNING,format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',datefmt='%a, %d %b %Y %H:%M:%S',filename='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", "db")# 创建连接
conn = pymysql.connect(host=db_host, user=db_user, passwd=db_pass, db=db, port=db_port, charset='utf8')
# 获取游标
cursor = conn.cursor()# 创建insert_sql
insert_blog_sql = ("INSERT IGNORE INTO blog(userid, id, blog_text, lat, lng, created_time) VALUES('{uid}', '{id}','{blog_text}','{lat}','{lng}','{created_time}')"
)insert_pic_sql = ("INSERT IGNORE INTO pics(pic_url, pic_bin, md5, exif) VALUES ('{pic_url}','{pic_bin}','{md5}','{exif}')"
)insert_relationship_sql = ("INSERT IGNORE INTO relationship(id, md5) VALUES ('{id}','{md5}')"
)uid = []with open('./data/final_id.txt', 'r') as f:for i in f.readlines():uid.append(i.strip('\r\n'))# 处理图片数据
def handle_pic(pic_url):large_pic_url = pic_url.replace('thumbnail', 'large')large_bin = requests.get(large_pic_url)return large_bin.contentdef get_poiid_info(uid):try:url = 'https://api.weibo.com/2/statuses/user_timeline.json'load = {'access_token': 'xxxxxxxxxx','uid': uid,'count': 100,'feature': 2,'trim_user': 1}get_info = requests.get(url=url, params=load, timeout=(10, 10))if get_info.status_code != 200:logging.warning(ConnectionError)passinfo_json = json.loads(get_info.content)info_json['uid'] = uidstatuses = info_json['statuses']# 处理筛选微博数据for status in statuses:id = status['idstr']if status['geo'] is not None:lat = status['geo']['coordinates'][0]lng = status['geo']['coordinates'][1]pic_urls = status['pic_urls']# 判断是否在北京if (115.7 < lng < 117.4) and (39.4 < lat < 41.6):# 若在北京,插入blog数据进库blog_text = status['text'].replace('\'', '\'\'')created_time = status['created_at']try:cursor.execute(insert_blog_sql.format(uid=uid, id=id, blog_text=blog_text, lat=lat, lng=lng,created_time=created_time))except pymysql.err.OperationalError as e_blog:logging.warning(e_blog.args[1])pass# conn.commit()# 处理图片for pic_url in pic_urls:# 获取原图片二进制数据pic_bin = handle_pic(pic_url['thumbnail_pic'])# 读取exif 数据pic_file = BytesIO(pic_bin)  # 将二进制数据转化成文件对象便于读取exif数据信息和生成MD5tag1 = exifread.process_file(pic_file, details=False, strict=True)tag = {}for key, value in tag1.items():if key not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename','EXIF MakerNote'):  # 去除四个不必要的exif属性,简化信息量tag[key] = str(value)tags = json.dumps(tag)  # dumps为json类型 此tag即为exif的json数据# 生成MD5MD5 = hashlib.md5(pic_file.read()).hexdigest()# 首先把二进制图片用base64 转成字符串之后再存try:cursor.execute(insert_pic_sql.format(pic_url=pic_url['thumbnail_pic'].replace('thumbnail', 'large'),pic_bin=str(base64.b64encode(pic_bin))[2:-1], md5=MD5,exif=tags))except pymysql.err.OperationalError as e_pic:logging.warning(e_pic.args[1])passtry:cursor.execute(insert_relationship_sql.format(id=id, md5=MD5))except pymysql.err.OperationalError as e_relation:logging.warning(e_relation)passconn.commit()else:logging.info(id + " is Not in Beijing")passelse:logging.info(id + ' Geo is null')passexcept pymysql.err.OperationalError as e:logging.error(e.args[1])passdef judge_conn(i):global conntry:conn.ping(True)get_poiid_info(i)except pymysql.err.OperationalError as e:logging.error('Reconnect')conn = pymysql.connect(host=db_host, user=db_user, passwd=db_pass, db=db, charset='utf8')get_poiid_info(i)def handle_tuple(a_tuple):read_uid_set = []for i in a_tuple:read_uid_set.append(i[0])return set(read_uid_set)if __name__ == '__main__':sql_find_uid = ("SELECT userid FROM blog")cursor.execute(sql_find_uid)read_uid_tuple = cursor.fetchall()read_list = handle_tuple(read_uid_tuple)print(len(read_list))new_uid = set(uid).difference(read_list)print(len(new_uid))pool = Pool()pool.map(judge_conn, list(new_uid))

个人博客

8aoy1.cn

爬取微博图片数据存到Mysql中遇到的各种坑\mysql存储图片\爬取微博图片相关推荐

  1. 爬取图片到mysql数据库_爬取微博图片数据存到Mysql中遇到的各种坑\mysql存储图片\爬取微博图片...

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

  2. 爬虫图片mysql_爬取微博图片数据存到Mysql中遇到的各种坑\爬取微博图片\Mysql存储图片\微博爬虫...

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

  3. mysql存储爬虫图片_爬取微博图片数据存到Mysql中遇到的各种坑\爬取微博图片\Mysql存储图片\微博爬虫...

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

  4. python爬取图片存入mysql_python爬取微博图片数据存到Mysql中遇到的各种坑

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

  5. 小猪的Python学习之旅 —— 14.项目实战:抓取豆瓣音乐Top 250数据存到Excel中

    小猪的Python学习之旅 -- 14.项目实战:抓取豆瓣音乐Top 250数据存到Excel中 标签:Python 一句话概括本文: 利用Excel存储爬到的抓取豆瓣音乐Top 250数据信息,还有 ...

  6. 抓取豆瓣音乐Top 250数据存到Excel中

    点击上方"程序员大咖",选择"置顶公众号" 关键时刻,第一时间送达! 引言: 失踪人口回归,最近比较迷茫,不知道是回头深究Android,还是继续 学Pytho ...

  7. mysql double 存储_关于MYSQL中FLOAT和DOUBLE类型的存储-阿里云开发者社区

    关于MYSQL中FLOAT和DOUBLE类型的存储 重庆八怪 2016-04-12 844浏览量 简介: 关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方 ...

  8. 关于MYSQL中FLOAT和DOUBLE类型的存储

    关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方式和C/C++一致准守IEEE标准他们都是浮点型的,所谓的浮点型,是小数点的位置可变,其能够表示的范围比定 ...

  9. mysql doen s exist_Mysql实例Mysql中大小写敏感问题导致的MySql Error 1146 Tabel doen’t exist错误...

    <Mysql实例Mysql中大小写敏感问题导致的MySql Error 1146 Tabel doen't exist错误>要点: 本文介绍了Mysql实例Mysql中大小写敏感问题导致的 ...

最新文章

  1. nvidia 英伟达 显卡 GPU 的计算能力
  2. ms17-010 php版本,那年MS17-010
  3. 你可能也看过这个生物学家转行后创造的价值 120 亿美元的动画
  4. hdfs的副本数为啥增加了_HDFS架构小结
  5. 【PostgreSQL-9.6.3】数据表操作语句
  6. session简单学习2
  7. window版GitHub使用
  8. Navivat 中快速快捷查找表和数据
  9. 一份ERP系统总体解决方案
  10. 19.Linux中字符处理sort和uniq命令详解
  11. 服务器被入侵了怎么办?
  12. Camtasia Studio 录制视频保存为camrec格式后快速导出为AVI格式
  13. 操作系统的分类有哪些?
  14. RFID卡片的扇区与块地址的关系
  15. PLSQL中的存储过程
  16. 《图解HTTP》阅读总结(上)
  17. CSS/HTML 5简洁带图标的input日期选择器
  18. HDU 6555 The Fool (整除分块 / 打表找规律)
  19. CMMI 级别有几级,详细定义是什么
  20. 【Stereo R-CNN 解读】基于立体R-CNN的自动驾驶三维目标检测

热门文章

  1. php yaf 2.3.5,php5.6安装Yaf2.3.5
  2. 解决微信二次分享bug
  3. Nature子刊:功能性脑架构与阿尔兹海默症tau蛋白聚集速率有关
  4. 什么是SOCKS5代理
  5. 有些程序员,本质是一群羊!
  6. [附源码]PHP计算机毕业设计星空摄影网站论文(程序+LW)
  7. 综合网络(华为ensp)
  8. 达观RPA网银自动对账机器人,财务一键对账So Easy!
  9. 磁共振t1t2信号记忆顺口溜_初学MRI记忆
  10. 金融直播需要准备什么直播设备?