删除MySQL重复数据的方法,Scrapy抓取拉勾网招聘信息

问题描述

查询数据库表中最近7天的记录

select count(*),date(create_time) as date from task where datediff(now(),create_time)<=6  group by day(create_time); 

 

但是发现某一天没有数据,结果中没有显示当天(2017-08-28)的数据

图片 1

删除MySQL重复数据的方法,mysql重复数据

本文实例讲述了删除MySQL重复数据的方法。分享给大家供大家参考。具体方法如下:

项目背景

在最近做的一个linux性能采集项目中,发现线程的程序入库很慢,再仔细定位,发现数据库里面很多冗余数据。因为在采集中,对于同一台设备,同一个时间点应该只有一个数据,然而,数据库中存入了多个数据。对于如何造成了这个结果,一时没有想清楚,但为了解决入库慢的问题,首先要删除冗余数据。

问题描述

数据库的表结构很简单,如下:

复制代码 代码如下:

+----------------+--------------+------+-----+---------+-------+
| Field          | Type         | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id             | varchar(255) | NO   | PRI | NULL    |       |
| conf_id        | varchar(255) | NO   | MUL | NULL    |       |
| insert_time    | datetime     | YES  |     | NULL    |       |
| cpu_usage      | float(11,2)  | YES  |     | NULL    |       |
| memory_usage   | float(11,2)  | YES  |     | NULL    |       |
| io_usage_write | float(11,2)  | YES  |     | NULL    |       |
| io_usage_read  | float(11,2)  | YES  |     | NULL    |       |
+----------------+--------------+------+-----+---------+-------+

查询所有数据量

复制代码 代码如下:

select count(*) from perf_linux;

输出 427366

查询所有时间点不同设备的数据量

复制代码 代码如下:

select count(distinct conf_id, insert_time) from perf_linux ;

输出42387

由上面的数据可以看出,数据冗余了10倍左右。

再按时间分组看一下:

复制代码 代码如下:

select id, conf_id ,insert_time from perf_linux order by insert_time, conf_id;

输出:

复制代码 代码如下:

| 2a79f7cd-43a9-4c7b-adb2-316b6c04283e | 1       | 2014-12-09 15:09:14 |
| 50d6f6c2-9c8b-45fd-98fd-2be211221cfd | 1       | 2014-12-09 15:09:14 |
| 740b52e1-e868-4074-ba36-74e2634401b3 | 1       | 2014-12-09 15:09:14 |
| 8b0096a4-9e85-417b-a131-e3505ca79a9c | 1       | 2014-12-09 15:09:14 |
| 90a9e882-5220-4508-a56f-8d4ab4a7929b | 1       | 2014-12-09 15:09:14 |
| d17403ed-24a4-45e8-b51b-2a95118383d9 | 1       | 2014-12-09 15:09:14 |
| 0c2da917-579b-4080-857d-7159f38b44ac | 2       | 2014-12-09 15:09:14 |
| 263083eb-8f63-4d2b-a03f-3320aa678735 | 2       | 2014-12-09 15:09:14 |
| d6c57a38-080b-465a-a55a-beafd9daf32d | 2       | 2014-12-09 15:09:14 |
| f672227b-1fb8-4b85-880d-2cc34b02880d | 2       | 2014-12-09 15:09:14 |
| f80020fe-6cb5-48ec-beb0-4e8ebeb0ca57 | 2       | 2014-12-09 15:09:14 |
| ff633a35-824d-49ba-b78c-5bcc5df8d1cc | 2       | 2014-12-09 15:09:14 |
| 5c41e48a-abfc-4108-a00e-ca7def7d5a5a | 3       | 2014-12-09 15:09:14 |
| 60b7ab9e-c91a-4020-a6d3-7bceb1dc47c5 | 3       | 2014-12-09 15:09:14 |
| 7b6cd2b8-ac6d-43eb-8858-e15885e676c8 | 3       | 2014-12-09 15:09:14 |
| d53a3df5-08c4-4604-8fac-cb51077935f6 | 3       | 2014-12-09 15:09:14 |
| d9e4ba14-f98d-42a8-b3bc-2879d58aa797 | 3       | 2014-12-09 15:09:14 |
| f56f82f6-32a7-47f7-ae07-b13168743884 | 3       | 2014-12-09 15:09:14 |
| 076c4c1b-0028-4a9c-a8c4-de655bd6ab6b | 4       | 2014-12-09 15:09:14 |
| 2a90ad9e-11a5-4707-95e8-78491da658ad | 4       | 2014-12-09 15:09:14 |
| 3b17ad1d-e589-4b65-93a7-d61fc99b4071 | 4       | 2014-12-09 15:09:14 |
| 6988d6cf-44ef-47f7-808d-09791caf2d90 | 4       | 2014-12-09 15:09:14 |
| 8404d281-f9e5-4153-a47e-128c05386758 | 4       | 2014-12-09 15:09:14 |
| e042e310-7ff2-4e4d-8c98-71e3e4d57828 | 4       | 2014-12-09 15:09:14 |
+--------------------------------------+---------+---------------------+

由上图可见,同一个时间点的同一个设备的数据有冗余,现在我们要把这些冗余数据去掉。

解决方法

思路是这样的:首先应该按照conf_id和时间点来判断,进行分组(group by)查询,每组中再取一个就可以。分组是很简单,但是分组怎么取一个呢?我采用了中间表的形式。

创建中间表,并把数据导入中间表

复制代码 代码如下:

create table perf_linux_t like perf_linux;
insert into perf_linux_t select * from perf_linux;

在中间表中增加一个字段,此字段是自增长的。

复制代码 代码如下:

ALTER TABLE `perf_linux_t`
ADD COLUMN `auto_id` INT NOT NULL AUTO_INCREMENT ,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`auto_id`);

删除无用数据

先查询一下

复制代码 代码如下:

select min(auto_id) as auto_id from perf_linux_t group by insert_time ;

删除不对的数据

复制代码 代码如下:

delete  from perf_linux_t where auto_id not in (select min(auto_id) as auto_id from perf_linux_t group by insert_time);

慢着,输出错误:

You can't specify target table 'perf_linux_t' for update in FROM clause

不能删除啊,那只能再建一个中间表了。

再建中间表

复制代码 代码如下:

create table tmp like perf_linux_t;

转变思路,不删除不符合的数据,而是把符合的数据存到这张新表中。

复制代码 代码如下:

insert into tmp select * from perf_linux_t where auto_id in (select min(auto_id) as auto_id from perf_linux_t group by insert_time,conf_id );

把这张表中的无用列删除

复制代码 代码如下:

ALTER TABLE `tmp`
DROP COLUMN `auto_id`,
DROP PRIMARY KEY;

导回数据

删除原来的数据

复制代码 代码如下:

truncate table perf_linux;

插入数据

复制代码 代码如下:

insert into perf_linux select * from tmp;

删除中间表

复制代码 代码如下:

drop table tmp;
drop table perf_linux_t;

总结

通过这个方法,数据变为了42387条,删除了冗余的数据。但实际上程序的问题并没有完全定位,还需要观察才能定位问题。

希望本文所述对大家的mysql数据库程序设计有所帮助。

本文实例讲述了删除MySQL重复数据的方法。分享给大家供大家参考。具体方法如下: 项目背景 在最...

前段时间自己做了个互联网职位分析的网站,本文将记录下整个数据获取的全部过程,之后还会有对数据进行可视化操作的介绍。该项目的所有代码均已放在github上。查看原文

解决思路

  1. 思路一: 可以在自己的程序中做额外的补零处理

  2. 思路二: 构建一个最近七天的结果集,然后和查询的结果集合做left join(本文采用第二种方式)

select a.click_date,b.count
from (
    SELECT curdate() as click_date
    union all
    SELECT date_sub(curdate(), interval 1 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 2 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 3 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 4 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 5 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 6 day) as click_date
) a left join (
  select date(create_time) as datetime, count(*) as count
  from arms_task
  group by date(create_time)
) b on a.click_date = b.datetime;

当天2017-08-28结果显示为NULL

图片 2

需要把NULL设置为0,利用ifnull函数即可

select a.click_date,ifnull(b.count,0) as count
from (
    SELECT curdate() as click_date
    union all
    SELECT date_sub(curdate(), interval 1 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 2 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 3 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 4 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 5 day) as click_date
    union all
    SELECT date_sub(curdate(), interval 6 day) as click_date
) a left join (
  select date(create_time) as datetime, count(*) as count
  from arms_task
  group by date(create_time)
) b on a.click_date = b.datetime;

 

图片 3

环境要求

请自行安装以下环境:

  • Win 7 (Scrapy在linux环境下不太稳定)
  • Scrapy
  • Scrapy,Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。
  • Python 2.7
  • Mysql
  • Chrome浏览器

思路分析

既然要抓取拉勾上所有的职位信息,那么必须要按照一定的顺序来爬取。
首先我们从搜索栏下手,试着搜索Python得到如下图:

sousuo.jpg

搜索结果下面有筛选的选项,这个时候大致思路就出来了,按照职位关键字和城市名称排列组合穷举出所有的职位信息。

具体实现

关键字、城市名获取

思路有了之后,我们先来获取职位关键字。
拉勾网的主页就列举了所有职位关键字,我们只需要跟互联网相关的就行了,这边有个小技巧就是可以直接在网页上复制粘贴下来关键字,稍微再处理下格式就行了。

keyword.jpg

当然城市名也一样,我们先分别保存为keyword.txt、 cityname.txt

寻找是否有可用api

一般情况下,这种网站都会有自己的api可用的,这时候我们可以用到浏览器的开发者工具,快捷键为F12。
在python的搜索结果中点击展开全部城市,在跳转到城市名的页面后,打开开发者工具下的network选项。

这时随便点击一个城市,可以看到其中有个链接

api_search_1.jpg

一眼看过去大概明白了这个api的用法
https://www.lagou.com/jobs/positionAjax.json?px=default&city=%E5%AE%89%E5%BA%86&needAddtionalResult=false
我们分析下这个url的组成,px=default这个参数看名字看不出来有什么意义,但是city参数不就是城市名吗?那职位关键字呢?仔细看上图,是通过POST方法传过去的,参数也很简单明了,kd就是关键字,pn就是页码。到了这一步,我们只需要写一个程序,将关键字和城市名排列组合一下,然后将返回结果筛选保存,这个数据获取的工作就算完成。

数据结构

在Mysql中创建一个数据库lagou,其中包括三张表

- city 城市名

+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(8) | NO | PRI | NULL | auto_increment |
| cityname | varchar(255) | NO | UNI | NULL | |
+----------+--------------+------+-----+---------+----------------+

* job_category 职位关键字
  * ```
+---------------------+--------------+------+-----+---------+----------------+
| Field               | Type         | Null | Key | Default | Extra          |
+---------------------+--------------+------+-----+---------+----------------+
| id                  | int(11)      | NO   | PRI | NULL    | auto_increment |
| job_name            | varchar(255) | NO   | UNI | NULL    |                |
| job_url             | varchar(255) | NO   |     | NULL    |                |
| job_category_level1 | varchar(255) | NO   |     | NULL    |                |
| job_category_level2 | varchar(255) | NO   |     | NULL    |                |
+---------------------+--------------+------+-----+---------+----------------+

- job_info 招聘信息

+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| id | int(8) | NO | PRI | NULL | auto_increment |
| keyword | varchar(255) | YES | | NULL | |
| positionName | varchar(255) | YES | | NULL | |
| salary | varchar(255) | YES | | NULL | |
| companySize | varchar(255) | YES | | NULL | |
| city | varchar(255) | YES | | NULL | |
| companyFullName | varchar(255) | YES | | NULL | |
| jobNature | varchar(255) | YES | | NULL | |
| workYear | varchar(255) | YES | | NULL | |
| education | varchar(255) | YES | | NULL | |
| positionId | varchar(255) | YES | UNI | NULL | |
| financeStage | varchar(255) | YES | | NULL | |
| industryField | varchar(255) | YES | | NULL | |
| approve | varchar(255) | YES | | NULL | |
| positionAdvantage | varchar(255) | YES | | NULL | |
| companyLabelList | varchar(255) | YES | | NULL | |
| score | varchar(255) | YES | | NULL | |
| adWord | varchar(255) | YES | | NULL | |
| createTime | varchar(255) | YES | | NULL | |
| companyId | varchar(255) | YES | | NULL | |
| companyShortName | varchar(255) | YES | | NULL | |
| district | varchar(255) | YES | | NULL | |
| businessZones | varchar(255) | YES | | NULL | |
| imState | varchar(255) | YES | | NULL | |
| lastLogin | varchar(255) | YES | | NULL | |
| publisherId | varchar(255) | YES | | NULL | |
| plus | varchar(255) | YES | | NULL | |
| pcShow | varchar(255) | YES | | NULL | |
| companyLogo | varchar(255) | YES | | NULL | |
| appShow | varchar(255) | YES | | NULL | |
| deliver | varchar(255) | YES | | NULL | |
| gradeDescription | varchar(255) | YES | | NULL | |
| formatCreateTime | varchar(255) | YES | | NULL | |
+-------------------+--------------+------+-----+---------+----------------+

将上面保存的cityname.txt和keyword.txt导入到数据库,这样更方便我们之后的操作。

# 总结
这一节先写到这边,主要是介绍思路和前期的准备工作,下一节进行代码的编写。

本文由澳门威斯尼人平台登录发布于澳门威斯尼人平台登录,转载请注明出处:删除MySQL重复数据的方法,Scrapy抓取拉勾网招聘信息

相关阅读