数据清洗与数据导入脚本

0 投票
3 回答
863 浏览
提问于 2025-04-15 22:42

我需要写一些脚本来在我的服务器上执行一些任务(服务器运行的是Ubuntu 8.04 TLS)。这些任务需要定期运行,所以我会把这些脚本设置成定时任务(cron jobs)。

我把任务分成了“A组”和“B组”,因为(至少在我看来)它们有点不同。

A组任务

  1. 从文件中导入数据,并可能对其进行重新格式化。这里的重新格式化是指像清理数据、标准化数据,或者对数据的某些“列”进行计算。

  2. 将处理过的数据导入到数据库中。目前,我主要使用mySQL来导入大部分数据,虽然有些文件会导入到sqlLite数据库。

注意:这些文件大多数是文本文件,虽然有些文件是二进制格式(我自己开发的C++应用程序生成的专有格式)。

B组任务

  1. 从数据库中提取数据。
  2. 对数据进行计算,并在数据库中插入或更新表格。

我的编程经验主要是C/C++开发者,过去两年我也在使用PHP(还有一些其他不相关的语言)。我来自Windows环境,所以在Linux环境中我还在适应中。

我想问的是——我需要写脚本来执行上述任务。虽然我可以写一些C++应用程序来配合这些脚本,但我觉得用脚本语言来写可能更好,但这可能是个错误的假设。我认为在脚本中修改东西会更简单——不需要重新编译等来更改功能。此外,C++处理数据通常需要的代码行数比像Perl、Python这样的“自然”脚本语言要多。

假设这里大多数人都同意用脚本语言来做,那么我面临的困扰是:我该用哪种脚本语言来执行上述任务(考虑到我的背景)?

我的直觉告诉我,Perl(打个寒颤)是执行所有这些任务的最明显选择。但是(这是个大问题)。提到Perl就让我感到不舒服,因为我之前有过非常糟糕的经历(很多年前买了Perl的《骆驼书》和《用Perl处理数据》,但还是没能理解,感觉太陌生了。尽管我尝试过很多次学习,但语法对我来说似乎很不自然,所以如果可以的话,我真的想避开它。至于PHP(我已经会了),我也不确定它是否适合在命令行下做脚本(我没有看到很多相关的例子,所以我可能错了)。

最后我必须提到的是,如果我必须学习一种新语言来完成这些任务,我没有时间(时间有限)去花超过一天的时间来学习所需的关键命令和功能(我可以在实际部署脚本后再学习语言的细节)。

所以,你会推荐我用哪种脚本语言(PHP、Python、Perl,或者你喜欢的其他语言)——最重要的是,为什么?或者,我是否应该继续写一些小的C++应用程序,然后在脚本中调用它们?

最后,如果你推荐了一种脚本语言,请用几行代码(Perl爱好者们,我在看着你们[不要太复杂!])展示一下我可以如何使用你推荐的语言来完成我想做的事情,比如:

  • 将CSV文件加载到某种数据结构中,以便可以轻松访问数据列进行处理。
  • 将列数据导入到mySQL表中。
  • 从mySQL表中加载数据到一种数据结构中,以便在脚本语言中访问行和列。

希望这些代码片段能让我快速识别出哪些语言的学习曲线最陡峭,以及哪些语言简单、优雅且高效(希望这两个标准[优雅和学习曲线平缓]不是相互矛盾的——尽管我怀疑它们可能会)。

3 个回答

1

我推荐你使用Python或Ruby。这两种语言比Perl要简单得多,学习起来会快很多,而且它们在处理数据方面也非常强大和高效。你应该能在一天之内学会其中一种,当然不算偶尔查查一些随机的库函数。

如果想快速学习Python,可以看看这个网站:http://diveintopython3.ep.io/

我个人没有推荐Ruby的教程,但我相信其他人会提供一些不错的选择。

如果你想试试这两种语言,可以访问http://www.trypython.orghttp://www.tryruby.org,这两个网站都有在线的交互式解释器,可以让你直接体验。

4

其实,我几年前也和你一样。当时我一点也不喜欢Perl,看到同事写的Perl脚本,我都会把它们改成Python,因为我实在受不了Perl。长话短说,现在我对Perl已经相当熟悉了。我推荐一本书叫《Impatient Perl》,这本书把重要的内容讲得很清楚,正是这本书让我爱上了Perl。 :)

这是一个任务A的示例脚本 - 用来读取一个文件,格式化它,然后写入数据库。

use autodie qw(:all);
use Text::CSV_XS ();
use DBI ();

my $csv = Text::CSV_XS->new({binary => 1}) 
  or die 'Cannot use CSV: ' . Text::CSV->error_diag;

{
    my $database_handle = DBI->connect(
        'dbi:SQLite:dbname=some_database_file.sqlite', undef, undef, {
            RaiseError => 1,
            AutoCommit => 1,
        },
    );
    $database_handle->do(
        q{CREATE TABLE something_table_or_other ('foo' CHAR(10), 'bar' CHAR(10), 'baz' CHAR(10), 'quux' CHAR(10), 'blah' CHAR(10))}
    );

    my $statement_handle = $database_handle->prepare(
        q{INSERT INTO something_table_or_other ('foo', 'bar', 'baz', 'quux', 'blah') VALUES (?, ?, ?, ?, ?)}
    );

    {
        open my $file_handle, '<:encoding(utf8)', 'data.csv';
        while (my $columns_aref = $csv->getline($file_handle)) {
            my @columns = @{ $columns_aref };

            # sanitize the columns - maybe substitute commas, numbers, etc.
            for (@columns) {
                s{,}{};  # substitutes commas with nothing
            }

            # insert columns into database now, using placeholders
            $statement_handle->execute(@columns);
        }
    }
}

注意:考虑到你现在对Perl的反感,我建议你用你熟悉的任何编程语言来完成上述“任务”。上面的内容只是想让你知道,Perl其实并没有那么难懂。当你不想重复自己时,才会显得复杂! :)

3

从文件中导入数据,并可能对其进行重新格式化。

Python在这方面非常出色。一定要了解一下csv模块,这样你就不用浪费时间自己去发明一个了。

如果是处理二进制数据,你可能需要用到struct模块。[如果你写了生成二进制数据的C++程序,可以考虑重写这个程序,避免使用二进制数据。这样长远来看会让你的生活简单很多。存储空间比你的时间便宜;高度压缩的二进制格式往往成本高于其价值。]

将处理过的数据导入数据库。 从数据库中提取数据。 对数据进行计算,然后插入或更新数据库中的表。

对于MySQL,可以使用mysqldb模块。SQLite是Python自带的。

通常,你会想使用对象关系映射,而不是自己写SQL语句。可以看看sqlobjectsqlalchemy这两个工具。

另外,在做太多之前,最好先买一本关于数据仓库的好书。你提到的两个“任务组”听起来像是你正在开始数据仓库的旅程。糟糕的数据库设计很容易让事情变得复杂。在做其他事情之前,先了解一下什么是“星型模式”。

撰写回答