banner
肥皂的小屋

肥皂的小屋

github
steam
bilibili
douban
tg_channel

Python3-固定文字分割のtxtをMySQLにバッチインポートする(長期更新)

厳重声明: 本記事で分析に使用したデータセットは学習交流のためのものであり、本文ではダウンロードリンクを提供しておらず、24 時間以内に削除されます。違法な目的に使用しないでください。そうした場合に生じるすべての結果は自己責任となります。

tb#

事の発端#

タスクの一つとして、手元のズボンの固定文字区切りの txt を mysql にインポートすることについて。

image

txt は 4 つのハイフン----でメールアドレスとパスワードを区切っています(私の魔法のマスキング技術は無視してください):

image

本記事では、Python を使用してこれらの固定文字区切りの txt をローカルのmysqlデータベースにバッチインポートする方法を試してみます。

一部のプロセスの説明は以下の通りです#

ファイルエンコーディングと改行コードについて#

ファイルエンコーディング#

もちろん、すべてのツールとファイルが utf8 エンコーディングであるのが最良です!

しかし、私が先ほど示したこの 4 つのテキストは、ダウンロードするとすべて:

ASCII text, with CRLF line terminators

手動で utf-8 に変更するとどうなるでしょうか?

UTF-8 Unicode (with BOM) text, with CRLF line terminators

image

この 2 つは普段最もよく見かけるものです。ああ?私がwinLinuxのコマンドを使える理由を尋ねますか?それは、偶然にもgit for windowsに非常に多くのLinuxコマンドが提供されていることを発見したからです。git for windowsVirtualboxからダウンロードするときに、インストールするかどうかの提示が表示されます。直接ダウンロードしてインストールすることもできます:ポータル

インストールしていない方には、ぜひインストールをお勧めします。非常に便利です(この 2 社が見ていたら広告費をください、ありがとうございます)。後でiconvsedなどのLinuxコマンドも使用します。

file xxx.txtコマンドを使用すると、ファイルのエンコーディングと改行コードを確認できます。

ANSIエンコーディングのtxtutf-8エンコーディングのデータベースにインポートしようとするとエラーが発生します:

image

1300, "Invalid utf8 character string: '˹'"

ここでは、すべてのファイルをUTF8エンコーディングに変換します。前述のコマンドラインのfileコマンドを使って試してみます。すぐに結果が得られます。

Pythonのコマンドライン文の実行については、前の記事《Python3 でコンピュータ上のすべての wifi アカウントとパスワードを表示する》で紹介しました。ここでは直接コードを示します:

import os
txt_name_list = ['260W.txt','316W.txt','440W.txt','445W.txt',]
for i in txt_name_list:
        print(os.popen('file {}'.format(i)).read())

結果は以下の通りです:

image

最初のものがUTF-8で、他はANSIですが、実際にはここで316W.txtUTF-8です。fileコマンドの正確性はあまり高くないことがわかります。

次に、Python3 のライブラリchardetを試してみます。参考記事:python によるテキストファイルのエンコーディング検出と変換

for i in txt_name_list:
        detector = UniversalDetector()
        print("検出中:{}のファイルエンコーディング".format(i))
        detector.reset()
        for line in open(i, 'rb').readlines():
            detector.feed(line)
            if detector.done:
                break
        detector.close()
        print(detector.result)

大きなファイルの検出は本当に遅いですが、長い間待った後、316W.txtUTF-8エンコーディングであることを検出できます。

readlines()1000000のパラメータを追加してみると、検出できません:

image

2000000行に増やすと再び検出できるようになります:

image

それでは、200Wを最大検出限界として使いましょう。

ファイルのエンコーディングを取得した後、utf8であるかどうかを判断し、そうでない場合はコマンドiconvを使用してファイルエンコーディングを変換し、名前を変更します:

src_enc = detector.result['encoding']
        # エンコーディングがutf-8でない場合、xx.txtをutf8-xx.txtに変換
        if 'utf-8' not in src_enc.lower():
            utf8_txt_name = "utf8-{}".format(i)
            print("{}はutf-8エンコーディングではありません。{}に変換中".format(i, utf8_txt_name))
            try:
                os.popen(
                    'iconv -c -f {} -t utf-8 {} > {}'.format(src_enc, i, utf8_txt_name))
            except Exception as e:
                print("変換エラー:{} \n プログラム終了!".format(e))
                exit(0)
            processed_txt_filename_list.append(utf8_txt_name)
        else:
            processed_txt_filename_list.append(i)

改行コード#

CRLF はキャリッジリターンとラインフィードを表し、CR はキャリッジリターン、LF はラインフィードです。通常は CRLF で十分です。CRLF は \n\r を表し、これは Windows のデフォルトの改行方式です。LF は \r を表し、これは Unix 系のデフォルトの改行方式です。

Unix 系のファイルを Windows で開くと、すべての文字が 1 行に変わります(VSCODE で開いても正常に表示されます。VSC が見ていたらお金をください、ありがとうございます);一方、Windows のファイルを Unix で開くと、各行の末尾に ^M 記号が追加されることがあります。

私は変更せず、すべてCRLFを使用します。変更したい場合は、sed コマンドを使用してすべての可能な\n\r\nに置き換えることもできます。

sed ’s/^M//’ filename > tmp_filename

他の方法については、参考記事:linux で Windows のファイルから \r を削除する

pymysql の基本操作#

pymysqlを使用してデータベースに接続し、sql文を実行する基本的な使い方は以下の通りです:

# データベースに接続、パスワードの後にデータベース名を追加できます
connect_mysql = pymysql.connect('localhost', 'root', 'root', charset='utf8')
# SQL文を実行できるカーソルオブジェクトを取得し、実行後の結果はデフォルトでタプル表示されます
cursor = connect_mysql.cursor()
# sql文を実行
cursor.execute('select * from `users`;')
# データベース接続を閉じる
connect_mysql.close()

しかし!pymysql.connect()関数を使用してデータベースに接続し、次のファイルのインポートコマンドload data local infile xxx.txtを実行すると、エラーが発生します:

image

1148, 'The used command is not allowed with this MySQL version'

インターネットで調べたところ、

セキュリティ上の理由から、デフォルトではクライアントホストから load data コマンドでデータをインポートすることは許可されていません。

この記事で解決策を見つけました:

connect_mysql = pymysql.connections.Connection('localhost', 'root', 'root',charset='utf8',local_infile=True)

全コードは以下の通りです:#

コメントは理解できると思いますが、疑問がある場合はコメントで一緒に議論しましょう~::quyin:1huaji::

#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
@author: soapffz
@function: 固定文字区切りのtxtをmysqlにバッチインポート
@time: 19-04-06
'''

import os  # テキスト名の取得とcmdコマンドの実行
import pymysql  # Python3ではpymysql、Python2ではmysqldb
from chardet.universaldetector import UniversalDetector  # ファイルエンコーディングの判断
import timeit  # 時間計測


def create_db():
    # データベースが存在しない場合は作成し、文字セットはutf8、照合順序はutf8_general_ci
    sql_create_db = "CREATE DATABASE IF NOT EXISTS `soendb` default charset utf8 COLLATE utf8_general_ci;"
    # taobaoというテーブルを作成し、2つのフィールドmailとpasswdを含む
    sql_create_table = """
    CREATE TABLE IF NOT EXISTS `taobao` (
        `mail` varchar(255) DEFAULT NULL,
        `passwd` varchar(255) DEFAULT NULL
        ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    """
    # 自分で作成する必要があるものを選択
    try:
        cursor.execute(sql_create_db)
        cursor.execute('use soendb;')  # 現在のデータベースを作成したばかりのデータベースに設定
        cursor.execute(sql_create_table)
    except Exception as e:  # すべての例外をキャッチして表示、python2ではException,e
        print("データベース作成エラー:{}\nプログラム終了!".format(e))
        connect_mysql.rollback()  # エラーが発生した場合はロールバック
        connect_mysql.close()  # データベース接続を閉じる
        exit(0)


def textencoding_lineterminators_modifi(txt_name_list):
    # テキストエンコーディングと文字の処理
    processed_txt_filename_list = []
    for i in txt_name_list:
        detector = UniversalDetector()
        print("検出中:{}のファイルエンコーディング".format(i))
        detector.reset()  # フィードプールをクリア
        for line in open(i, 'rb').readlines(20000000):  # 200W行をイテレートし、結果を検出するのに十分
            detector.feed(line)  # フィード
            if detector.done:  # 結果があれば、終了
                break
        detector.close()
        src_enc = detector.result['encoding']
        # エンコーディングがutf-8でない場合、xx.txtをutf8-xx.txtに変換
        if 'utf-8' not in src_enc.lower():
            utf8_txt_name = "utf8-{}".format(i)
            print("{}はutf-8エンコーディングではありません。{}に変換中".format(i, utf8_txt_name))
            try:
                os.popen(
                    'iconv -c -f {} -t utf-8 {} > {}'.format(src_enc, i, utf8_txt_name))
            except Exception as e:
                print("変換エラー:{} \n プログラム終了!".format(e))
                exit(0)
            processed_txt_filename_list.append(utf8_txt_name)
        else:
            processed_txt_filename_list.append(i)
    return processed_txt_filename_list


def import_txt_to_mysql(txt_name):
    # txtをmysqlにインポート
    sql_insert_txt = """
    LOAD DATA LOCAL INFILE "{}" INTO TABLE `taobao`
    FIELDS TERMINATED BY '----' LINES TERMINATED BY '\r\n';
    """.format(txt_name)
    # --フィールドは'----'で区切られ(例)、レコードはCRLFで区切られます(例)
    try:
        cursor.execute('use soendb;')
        cursor.execute(sql_insert_txt)
        # データベースに実行をコミット
        connect_mysql.commit()
    except Exception as e:
        print("データインポートエラー:{}\nプログラム終了!".format(e))
        connect_mysql.rollback()
        connect_mysql.close()
        exit(0)


if __name__ == "__main__":
    start_time = timeit.default_timer()
    # データベースに接続、パスワードの後にデータベース名を追加できます
    try:
        connect_mysql = pymysql.connections.Connection(
            'localhost', 'root', 'root', charset='utf8', local_infile=True)
        # SQL文を実行できるカーソルオブジェクトを取得し、実行後の結果はデフォルトでタプル表示されます
        cursor = connect_mysql.cursor()
    except Exception as e:
        print("データベース接続エラー :{}\nプログラム終了!".format(e))
        exit(0)
    print("データベース接続成功")
    create_db()  # オプション、データベースとテーブルを作成
    # 現在のディレクトリのすべてのtxtファイルのファイル名を取得
    src_txt_filename_list = [filename for filename in os.listdir(
        ".") if filename.split(".")[-1] == 'txt']
    if src_txt_filename_list:  # 現在のディレクトリのtxt名リストが空でない場合、リストを取得してエンコーディングを検出し、新しいtxt名リストを取得
        processed_txt_filename_list = textencoding_lineterminators_modifi(
            src_txt_filename_list)
        for txt_name in processed_txt_filename_list:
            try:
                print("インポート中:{}".format(txt_name))
                import_txt_to_mysql(txt_name)
            except Exception as e:
                print("データインポートエラー:{}\nプログラム終了!".format(e))
                connect_mysql.rollback()
                connect_mysql.close()
                exit(0)
    else:
        print("txtファイル名を取得できませんでした。再度確認してください!")
    end_time = timeit.default_timer()
    print("データベースインポート完了、総時間{}".format(end_time-start_time))

結果は以下の通りです:

image

image

実際には 200 秒以上かかり、99% 以上の時間がファイルのエンコーディングの検証に費やされていますが、私が文中で述べたように、fileコマンドの正確性は基本的にchardetの検出信頼度が 100% のエンコーディングのファイルにしか適用されず、他のものはほとんど無意味ですが、chardetの速度は非常に遅いです。200W 行の上限を設定したにもかかわらず。

もちろん、検証を行わず、すべてのファイルをutf-8エンコーディングに変換することもできます。

したがって、Windowsで(Linuxの場合も、Windowsで見つけられると良いですが)バッチ検証とファイルエンコーディングの変更ツールがあれば、ぜひコメントで議論しましょう。

注意:

  • ファイルのパスは / でなければなりませんが、win でコピーするとデフォルトは \ になります。本文では処理していませんが、この py ファイルは txt があるディレクトリに配置されているため、パスの問題はありません。
  • 挿入、更新、削除などの操作には、connect_mysql.commit () を使用してデータベースに実行をコミットする必要がありますが、クエリ、データベースやデータテーブルの作成操作にはこの文は必要ありません。
  • 実際には、大部分のコードは繰り返しですが、読みやすさを考慮し、また一部の読者が特定の機能を使用しない可能性があるため、分けて書きました。

参考リンク:


BreachCompilation#

[19-4-10 更新] 各ファイルのエンコーディングを検出するのは本当に手間がかかります。私は安全脈搏の 14 億漏洩データを整理記事として整理し、Freebuf などのウェブサイトで公開されたデータセキュリティコンサルティング記事を整理しているとき、ここにあるデータはこのようになっています:

image

多くのフォルダにはサブフォルダがあり、データファイルには拡張子がありません。主にcat * > 1.txtというコマンドを使用して、指定されたフォルダに統合します。

コードがほぼ完成したとき、シェルの 1 つのコマンドでフォルダ内(サブフォルダを含む)のすべてのファイルを統合できることに気づきました。参考記事

> find . 現在のフォルダからファイルを再帰的に検索
> -type f 通常のファイルとしてファイルタイプを指定、他に選択できる項目には:d ディレクトリ、l シンボリックリンク、c キャラクタデバイス、b ブロックデバイス、s ソケットなどがあります
> -amin/-mmin/-cmin アクセス時間/変更時間/変更時間を指定できます。例:find . -type f -atime +7 -print アクセス時間が7日を超えるすべてのファイルを印刷
> -perm ファイルの権限でファイルを検索
> -user ファイルの所有者でファイルを検索
> -delete 検索したファイルを削除します
> -exec 検索したファイルにコマンドを実行します。形式は: -exec ./commands.sh {} \;

その時の心境は崩壊寸前でした::quyin:hematemesis::。幸い、winに付属のfindコマンドはファイル内の文字列しか検索できず、インストールしたGitは、Unixを使用してwinに付属の一部のコマンドを上書きするオプションを選択しても、findを使用できないため、心境は再び正常に戻りました::quyin:witty::

テキスト整理の主なコアコマンド:各フォルダに入り、catコマンドを実行し、各コマンドはブロックせず、マルチスレッドで互いに干渉しないことを希望します。

参考記事:Python で cmd を実行するさまざまな実装方法とその長所と短所(subprocess.Popen、os.system、commands.getstatusoutput)

この文章に補足します:

os.system () この関数はブロッキングですが、エラーメッセージは返さず、各コマンドは次のコマンドを実行する前に完了する必要があります。
3.x バージョンでは、commands ライブラリの 3 つのメソッドの 1 つである getstatus () メソッドが削除され、getoutput () と getstatusoutput () が subprocess モジュールに移動されました。(つまり、3.x バージョンでは commands ライブラリは使用されず、subprocess ライブラリが使用されます)

以下は全コードです:

#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
@author: soapffz
@function: 固定文字区切りのtxtをmysqlにバッチインポート(粗いエンコーディング変換)
@time: 19-04-11
'''

import os  # テキスト名の取得とcmdコマンドの実行
import shutil  # ファイルとディレクトリに関連する処理
import subprocess  # cmdコマンドの実行
import pymysql  # Python3ではpymysql、Python2ではmysqldb
import timeit  # 時間計測
import re  # 正規表現を使用してファイル名を分離

class db_progress:
    def __init__(self):
        self.collections_dir = 'E:\Pants\BreachCompilation\collections'
        self.connect_mysql()
        self.create_db()

    def connect_mysql(self):
        # データベースに接続、パスワードの後にデータベース名を追加できます
        try:
            self.mysql_conn = pymysql.connections.Connection(
                'localhost', 'root', 'root', charset='utf8', local_infile=True)
            # SQL文を実行できるカーソルオブジェクトを取得し、実行後の結果はデフォルトでタプル表示されます
            self.cursor = self.mysql_conn.cursor()
            print("データベース接続成功")
        except Exception as e:
            print("データベース接続エラー :{}\nプログラム終了!".format(e))
            exit(0)

    def create_db(self):
        # データベースが存在しない場合は作成し、文字セットはutf8、照合順序はutf8_general_ci
        sql_create_db = "CREATE DATABASE IF NOT EXISTS `14yi` default charset utf8 COLLATE utf8_general_ci;"
        # 自分で作成する必要があるものを選択
        try:
            self.cursor.execute(sql_create_db)
            self.cursor.execute('use 14yi;')  # 現在のデータベースを作成したばかりのデータベースに設定
        except Exception as e:  # すべての例外をキャッチして表示、python2ではException,e
            print("データベース作成エラー:{}\nプログラム終了!".format(e))
            self.mysql_conn.rollback()  # エラーが発生した場合はロールバック
            self.mysql_conn.close()  # データベース接続を閉じる
            exit(0)

    def import_txt_to_mysql(self, txt_name_list):
        if not txt_name_list:
            # txt_name_listが取得できない場合、ファイルエンコーディング処理が失敗したことを示します
            print("ファイルエンコーディングが誤っている可能性があります。txt名リストが取得できませんでした。再度確認してください!\nプログラム終了!")
            print(0)
        else:
            # 現在の作業ディレクトリをcollectionsフォルダに移動
            os.chdir(self.collections_dir)
            # txtをmysqlにインポート
            for txt_name in txt_name_list:
                table_name = re.findall(".*data-(.*).txt", txt_name)[0]
                # 2つのフィールドmailとpasswdを含むテーブルを作成
                sql_create_table = """
                CREATE TABLE IF NOT EXISTS `{}` (
                    `mail` varchar(255) DEFAULT NULL,
                    `passwd` varchar(255) DEFAULT NULL
                ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
                """.format(table_name)
                # データをデータベースに挿入
                sql_insert_txt = """
                LOAD DATA LOCAL INFILE "{}" INTO TABLE `{}`
                FIELDS TERMINATED BY ':' LINES TERMINATED BY '\n';
                """.format(txt_name, table_name)
                # --フィールドは':'で区切られ(例)、レコードはLFCRで区切られます(例)
                try:
                    print("インポート中:{}".format(txt_name))
                    self.cursor.execute('use 14yi;')
                    self.cursor.execute(sql_create_table)
                    self.cursor.execute(sql_insert_txt)
                    self.mysql_conn.commit()  # データベースに実行をコミット
                except Exception as e:
                    print("データインポートエラー:{}\nプログラム終了!".format(e))
                    self.mysql_conn.rollback()
                    self.mysql_conn.close()
                    exit(0)

class txt_progress:
    def __init__(self):
        self.root_dir = 'data'
        self.collections_dir = 'E:\Pants\BreachCompilation\collections'
        self.utf8_txt_name_list = []
        if os.path.exists(self.collections_dir):
            # ディレクトリが存在する場合、サブフォルダも含めて削除
            shutil.rmtree(self.collections_dir)
        os.mkdir(self.collections_dir)
        self.txt_collections(self.root_dir)
        self.txt_coding_conv()

    def txt_collections(self, path):
        # 各フォルダ内のファイルをcatコマンドでcollections_dirフォルダに保存
        for item in os.listdir(path):
            subFile = os.path.join(path + "\\" + item)
            if os.path.isdir(subFile):
                try:
                    # 正規表現を使用してファイル名を分離
                    txt_name = os.path.join(self.collections_dir, re.split(
                        r'BreachCompilation\\', os.path.abspath(subFile))[-1].replace("\\", '-'))
                    print("変換中:{}".format(txt_name))
                    # 各フォルダに入り、各フォルダ内のすべての内容をcollectionsの対応する名前のtxtに統合
                    cc = 'cd {} && cat * > {}.txt'.format(
                        os.path.abspath(subFile), txt_name)
                    subprocess.run(cc, shell=True, stdout=subprocess.PIPE)
                except Exception as e:
                    print("変換エラー:{} \n プログラム終了!".format(e))
                    exit(0)
                self.txt_collections(subFile)

    def txt_coding_conv(self):
        os.chdir(self.collections_dir)
        # collections_dirフォルダ内のすべてのファイルをutf-8エンコーディングに変換し、insert_txt_to_mysql関数に供給するtxt_name_listを返します
        for item in os.listdir("."):
            try:
                utf8_txt_name = "utf8{}".format(item)  # 新しい名前
                # すべてのtxtをutf-8エンコーディングに強制的に変換
                subprocess.run('iconv -c -f ISO-8859-1 -t utf-8 {} > {}'.format(
                    item, utf8_txt_name), shell=True, stdout=subprocess.PIPE)
                self.utf8_txt_name_list.append(utf8_txt_name)
            except Exception as e:
                print("変換エラー:{} \n プログラム終了!".format(e))
                exit(0)
        return self.utf8_txt_name_list

if __name__ == "__main__":
    start_time = timeit.default_timer()
    progress_db = db_progress()
    progress_txt = txt_progress()
    # 変換後のutf8-_txt_name_listをデータベースインポート関数に渡す
    progress_db.import_txt_to_mysql(progress_txt.utf8_txt_name_list)
    end_time = timeit.default_timer()
    print("プログラム実行完了、総時間{}".format(end_time-start_time))

結果は以下の通りです:

一時的には効果がなく、まだ小さな問題があります。


7x7x#

[19-04-13 更新] テンプレートができたので、他の固定文字区切りの txt を mysql にインポートする問題は非常に簡単です。テンプレートを変更するだけで済みます。

今回はある国内ゲームサイト 7x7x のデータベース(インターネットで収集されたもの):

image

\tを区切り文字として使用するこのデータベースの特異な点は、同時にメールアドレス\tパスワードユーザー名\tパスワードの 2 種類のデータが存在することです:

image

したがって、テーブルを作成する際には、3 つのフィールド:emailpasswdusernameを作成する必要があります。

@記号を含まない行が検出された場合(つまり、メールアドレスを含まない場合)、\tパスワード\tユーザー名の形式に再構成します(email-passwdのデータが大部分を占めるため、usernameを最後に配置します)。

全コードは以下の通りです:

#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
@author: soapffz
@function: 7k7kデータベースから固定文字区切りのtxtをmysqlにバッチインポート(エンコーディング変換)
@Comment: 7k7kのこれらのテキストはテキストエンコーディング精密検出方法で検出され、すべてutf-8であるため、プログラム内でエンコーディング変換を追加しません。
@comment: ただし、メールアドレス-パスワードとユーザー名-パスワードがあるため、テキスト整理関数を追加します。
@time: 19-04-13
'''

import os  # テキスト名の取得とcmdコマンドの実行
import subprocess
import pymysql  # Python3ではpymysql、Python2ではmysqldb
import timeit  # 時間計測
import re  # 正規表現を使用してファイル名を分離

class db_progress(object):
    def __init__(self):
        self.connect_mysql()
        self.create_db()

    def connect_mysql(self):
        # データベースに接続、パスワードの後にデータベース名を追加できます
        try:
            self.mysql_conn = pymysql.connections.Connection(
                'localhost', 'root', 'root', charset='utf8', local_infile=True)
            # SQL文を実行できるカーソルオブジェクトを取得し、実行後の結果はデフォルトでタプル表示されます
            self.cursor = self.mysql_conn.cursor()
            print("データベース接続成功")
        except Exception as e:
            print("データベース接続エラー :{}\nプログラム終了!".format(e))
            exit(0)

    def create_db(self):
        # データベースが存在しない場合は作成し、文字セットはutf8、照合順序はutf8_general_ci
        sql_create_db = "CREATE DATABASE IF NOT EXISTS `soendb` default charset utf8 COLLATE utf8_general_ci;"
        # テーブルが存在するかどうかを検出し、存在する場合は削除してから作成
        sql_table_detection = "DROP TABLE IF EXISTS `7k7k`;"
        sql_create_table = """
            CREATE TABLE `7k7k` (
                `email` varchar(255) DEFAULT NULL,
                `passwd` varchar(255) DEFAULT NULL,
                `username` varchar(255) DEFAULT NULL
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
            """
        try:
            self.cursor.execute(sql_create_db)
            self.cursor.execute('use soendb;')  # 現在のデータベースを作成したばかりのデータベースに設定
            self.cursor.execute(sql_table_detection)  # テーブルが存在するかどうかを検出し、存在する場合は削除してから作成
            self.cursor.execute(sql_create_table)
        except Exception as e:  # すべての例外をキャッチして表示、python2ではException,e
            print("データベース作成エラー:{}\nプログラム終了!".format(e))
            self.mysql_conn.rollback()  # エラーが発生した場合はロールバック
            self.mysql_conn.close()  # データベース接続を閉じる
            exit(0)

    def import_txt_to_mysql(self, txt_name_list):
        if not txt_name_list:
            # txt_name_listが取得できない場合、ファイルエンコーディング処理が失敗したことを示します
            print("ファイルエンコーディングが誤っている可能性があります。txt名リストが取得できませんでした。再度確認してください!\nプログラム終了!")
            exit(0)
        else:
            # txtをmysqlにインポート
            for txt_name in txt_name_list:
                sql_insert_txt = """
                LOAD DATA LOCAL INFILE "{}" IGNORE INTO TABLE `7k7k`
                FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\r\n';
                """.format(txt_name)
                # --フィールドは'\t'で区切られ(例)、レコードはLFCRで区切られます(例)
                try:
                    print("インポート中:{}".format(txt_name))
                    self.cursor.execute('use soendb;')
                    self.cursor.execute(sql_insert_txt)
                    self.mysql_conn.commit()  # データベースに実行をコミット
                except Exception as e:
                    print("データインポートエラー:{}\nプログラム終了!".format(e))
                    self.mysql_conn.rollback()
                    self.mysql_conn.close()
                    exit(0)

class txt_progress:
    def __init__(self):
        self.processed_txt_filename_list = []
        self.txt_process()

    def txt_process(self):
        # メールアドレス-パスワードとユーザー名-パスワードの両方を含むテキストを整理
        # 特殊文字をフィルタリング
        special_characters = ['?', 'ú', 'ü']
        for i in os.listdir("."):
            if os.path.splitext(i)[1] == ".txt":
                print("整理中:{}".format(i))
                with open(i, 'r', encoding='utf-8') as f:
                    processed_txt_name = "processed-{}".format(i)
                    with open(processed_txt_name, 'a', encoding='utf-8') as k:
                        for j in f.readlines():
                            # 特殊文字を含む行を削除
                            if any(chs in j for chs in special_characters):
                                continue
                            split = j.split('\t')
                            # アカウントまたはパスワードが存在しない場合、その行を削除
                            if '' in split:
                                continue
                            # パスワードに中国語が含まれている場合、その行を削除
                            if re.compile(u'[\u4e00-\u9fa5]').search(split[-1]):
                                continue
                            # ユーザー名がメールアドレスでない場合、再配置:\tパスワード\tユーザー名\n
                            if '@' not in split[0]:
                                j = '\t' + \
                                    split[-1].strip('\n') + \
                                    '\t' + split[0] + '\n'
                            k.write(j)
                    self.processed_txt_filename_list.append(processed_txt_name)
        return self.processed_txt_filename_list

if __name__ == "__main__":
    start_time = timeit.default_timer()
    progress_db = db_progress()
    progress_txt = txt_progress()
    progress_db.import_txt_to_mysql(progress_txt.processed_txt_filename_list)
    end_time = timeit.default_timer()
    print("プログラム実行完了、総時間{}".format(end_time-start_time))

実行結果は以下の通りです:

image

image

image

image

厳重声明: 本記事で分析に使用したデータセットは学習交流のためのものであり、本文ではダウンロードリンクを提供しておらず、24 時間以内に削除されます。違法な目的に使用しないでください。そうした場合に生じるすべての結果は自己責任となります。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。