千万级网络爬虫设计狂想曲
前言:
研究采集多年,感觉网络爬虫技术实现起来并不是太复杂,只要有足够的硬件,都可以做到分布式,整个爬虫环节,感觉最难也是最复杂的,还是数据库的设计!
目前主流的数据库常用的就是mysql数据库,语法方面也比较亲切,有手感!本文也就针对千万级大数据,如何去重, 写一下自己的想法,而后的实践在做记录!
正文:
爬虫每天大概生产50万的信息量,主要字段包括 标题 作者 url 采集时间 是否有效 检测时间 (嘿,猜吧,这到底是采集的什么鬼东西?!!!!!)
随着数据库的不断膨胀,目前大概已经存在大概3000万条信息量,逐渐面对数据去重的问题!
关于数据入库的一些构想:
新增一列字段,对标题和作者进行唯一hash,MD5加密,并设置索引,选择16位md5值即可, 字段选择char `md5` char(32) NOT NULL COMMENT 'title和username的合并md5值',
update mycode_caiji set md5=md5(CONCAT(title,username));
update mycode_all set md5=substring(`md5`,9,16);
仅仅这样还不行,还可以对MD5值进行拆分,
再增加一列,这一列选取MD5值的前四位进行16进制转10进制存储,别小看这一列的作用,对于上亿级别的数据,也可以filter掉一个数量级的筛选.
这里把16进制转10进制是因为,mysql对整数的查询速度远远大于字符的速度,所以尽量转换成int类型的
如果绝对还是不够,那么可以再增加一些字段,添加sha1的前几位,或者后几位,总之对数据分类越精细越好!然后对新增的字段添加索引!
用存储换时间,还是用时间换存储,不可兼得啊!!!!!!!
网上建议对md5设置唯一索引,曾测试了一下,发现随着数据量的增多,插入速度会越来越慢,还是在前端生成md5值比对,这样减轻数据库压力!
爬虫采集万数据,入库的时候可以类似这样查询:
select id from mycode_all where splitmd5=11111 and md5='7a57a5a743894a0e'
如果存在,就不再插入
-------------------------------------------------------------------------
前端查询就采用分表操作,如果是有1000万数据,那么可以分成10个表,每个表100万
框架处理语法大概或许可能像下面这样:
以上只是本人的一点想法,记录一下,.不作为生产环境的参考!
研究采集多年,感觉网络爬虫技术实现起来并不是太复杂,只要有足够的硬件,都可以做到分布式,整个爬虫环节,感觉最难也是最复杂的,还是数据库的设计!
目前主流的数据库常用的就是mysql数据库,语法方面也比较亲切,有手感!本文也就针对千万级大数据,如何去重, 写一下自己的想法,而后的实践在做记录!
正文:
爬虫每天大概生产50万的信息量,主要字段包括 标题 作者 url 采集时间 是否有效 检测时间 (嘿,猜吧,这到底是采集的什么鬼东西?!!!!!)
随着数据库的不断膨胀,目前大概已经存在大概3000万条信息量,逐渐面对数据去重的问题!
关于数据入库的一些构想:
把一个唯一md5值打散成三份 三个字段
第一个字段,截取md5值的前4位 SELECT CONV('d',16,10); 以十进制的数字保存
第二个字段,截取md5值的中间16位 以char 保存 创建索引
这样通过filter函数基本上可以过滤掉一个数量级的查询
新增一列字段,对标题和作者进行唯一hash,MD5加密,并设置索引,选择16位md5值即可, 字段选择char `md5` char(32) NOT NULL COMMENT 'title和username的合并md5值',
update mycode_caiji set md5=md5(CONCAT(title,username));
update mycode_all set md5=substring(`md5`,9,16);
仅仅这样还不行,还可以对MD5值进行拆分,
再增加一列,这一列选取MD5值的前四位进行16进制转10进制存储,别小看这一列的作用,对于上亿级别的数据,也可以filter掉一个数量级的筛选.
这里把16进制转10进制是因为,mysql对整数的查询速度远远大于字符的速度,所以尽量转换成int类型的
如果绝对还是不够,那么可以再增加一些字段,添加sha1的前几位,或者后几位,总之对数据分类越精细越好!然后对新增的字段添加索引!
用存储换时间,还是用时间换存储,不可兼得啊!!!!!!!
网上建议对md5设置唯一索引,曾测试了一下,发现随着数据量的增多,插入速度会越来越慢,还是在前端生成md5值比对,这样减轻数据库压力!
爬虫采集万数据,入库的时候可以类似这样查询:
select id from mycode_all where splitmd5=11111 and md5='7a57a5a743894a0e'
如果存在,就不再插入
-------------------------------------------------------------------------
前端查询就采用分表操作,如果是有1000万数据,那么可以分成10个表,每个表100万
框架处理语法大概或许可能像下面这样:
#! /usr/bin/env python #coding=utf-8 #by tools.bugscaner.com import sys import re import json import pickle #url参数编码 from urllib import quote #models转字典 from django.forms.models import model_to_dict from django.http import HttpResponse from django.shortcuts import render_to_response #载入目前已塞满的数据库模型 from mycode.models import (A,B,C,D,E,F) #载入加密和解密模块 from mycode.aes import encode,decode reload(sys) sys.setdefaultencoding("utf-8") #这里列出数据库的表 alltables = {"a":A,"b":B,"c":C,"d":D,"e":E,"f":F} #每个表id和allid的等差 prefix = {"a":0,"b":1500000,"c":3000000,"d":4500000,"e":6000000,"f":7500000} table_object = alltables.get(tables) |
以上只是本人的一点想法,记录一下,.不作为生产环境的参考!