厳重声明: 本記事で分析に使用したデータセットは学習交流のためのものであり、本文ではダウンロードリンクを提供しておらず、24 時間以内に削除されます。違法な目的に使用しないでください。そうした場合に生じるすべての結果は自己責任となります。
tb#
事の発端#
タスクの一つとして、手元のズボンの固定文字区切りの txt を mysql にインポートすることについて。
txt は 4 つのハイフン----
でメールアドレスとパスワードを区切っています(私の魔法のマスキング技術は無視してください):
本記事では、Python を使用してこれらの固定文字区切りの txt をローカルのmysql
データベースにバッチインポートする方法を試してみます。
一部のプロセスの説明は以下の通りです#
ファイルエンコーディングと改行コードについて#
ファイルエンコーディング#
もちろん、すべてのツールとファイルが utf8 エンコーディングであるのが最良です!
しかし、私が先ほど示したこの 4 つのテキストは、ダウンロードするとすべて:
ASCII text, with CRLF line terminators
手動で utf-8 に変更するとどうなるでしょうか?
UTF-8 Unicode (with BOM) text, with CRLF line terminators
この 2 つは普段最もよく見かけるものです。ああ?私がwin
でLinux
のコマンドを使える理由を尋ねますか?それは、偶然にもgit for windows
に非常に多くのLinux
コマンドが提供されていることを発見したからです。git for windows
をVirtualboxからダウンロードするときに、インストールするかどうかの提示が表示されます。直接ダウンロードしてインストールすることもできます:ポータル
インストールしていない方には、ぜひインストールをお勧めします。非常に便利です(この 2 社が見ていたら広告費をください、ありがとうございます)。後でiconv
、sed
などのLinux
コマンドも使用します。
file xxx.txt
コマンドを使用すると、ファイルのエンコーディングと改行コードを確認できます。
ANSI
エンコーディングのtxt
をutf-8
エンコーディングのデータベースにインポートしようとするとエラーが発生します:
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())
結果は以下の通りです:
最初のものがUTF-8
で、他はANSI
ですが、実際にはここで316W.txt
もUTF-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.txt
がUTF-8
エンコーディングであることを検出できます。
readlines()
に1000000
のパラメータを追加してみると、検出できません:
2000000
行に増やすと再び検出できるようになります:
それでは、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
を実行すると、エラーが発生します:
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))
結果は以下の通りです:
実際には 200 秒以上かかり、99% 以上の時間がファイルのエンコーディングの検証に費やされていますが、私が文中で述べたように、file
コマンドの正確性は基本的にchardet
の検出信頼度が 100% のエンコーディングのファイルにしか適用されず、他のものはほとんど無意味ですが、chardet
の速度は非常に遅いです。200W 行の上限を設定したにもかかわらず。
もちろん、検証を行わず、すべてのファイルをutf-8
エンコーディングに変換することもできます。
したがって、Windows
で(Linux
の場合も、Windows
で見つけられると良いですが)バッチ検証とファイルエンコーディングの変更ツールがあれば、ぜひコメントで議論しましょう。
注意:
- ファイルのパスは / でなければなりませんが、win でコピーするとデフォルトは \ になります。本文では処理していませんが、この py ファイルは txt があるディレクトリに配置されているため、パスの問題はありません。
- 挿入、更新、削除などの操作には、connect_mysql.commit () を使用してデータベースに実行をコミットする必要がありますが、クエリ、データベースやデータテーブルの作成操作にはこの文は必要ありません。
- 実際には、大部分のコードは繰り返しですが、読みやすさを考慮し、また一部の読者が特定の機能を使用しない可能性があるため、分けて書きました。
参考リンク:
- python によるテキストファイルのエンコーディング検出と変換
- linux で Windows のファイルから \r を削除する
- Python3 MySQL データベース接続 - PyMySQL ドライバ
- PyMySQL の基本的な使用法
- PyMYSQL モジュール
BreachCompilation#
[19-4-10 更新] 各ファイルのエンコーディングを検出するのは本当に手間がかかります。私は安全脈搏の 14 億漏洩データを整理記事として整理し、Freebuf などのウェブサイトで公開されたデータセキュリティコンサルティング記事を整理しているとき、ここにあるデータはこのようになっています:
多くのフォルダにはサブフォルダがあり、データファイルには拡張子がありません。主に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 のデータベース(インターネットで収集されたもの):
\t
を区切り文字として使用するこのデータベースの特異な点は、同時にメールアドレス\tパスワード
とユーザー名\tパスワード
の 2 種類のデータが存在することです:
したがって、テーブルを作成する際には、3 つのフィールド:email
、passwd
、username
を作成する必要があります。
@
記号を含まない行が検出された場合(つまり、メールアドレスを含まない場合)、\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))
実行結果は以下の通りです:
厳重声明: 本記事で分析に使用したデータセットは学習交流のためのものであり、本文ではダウンロードリンクを提供しておらず、24 時間以内に削除されます。違法な目的に使用しないでください。そうした場合に生じるすべての結果は自己責任となります。