質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

Q&A

1回答

1124閲覧

virustotal api を使用したpython3においてのエラー

peromaron

総合スコア7

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

0グッド

0クリップ

投稿2018/03/21 11:00

編集2018/03/23 15:39

前提・実現したいこと

仮想上でpython3にてVirusTotalのApiを複数使用してその結果をデータベースに格納したいです。

発生している問題・エラーメッセージ

エラーメッセージ

①最終文のself.cursor.execute('update analysis_results set search_time =now(), analysis_result = 1, updated_at =now()') #% str(decjson ["positives"])
analysis_result = 1 の =1を =%dにした場合のエラー (指定した数でなく変数を入れたい)

mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '+= 1 where id = 1' at line 1

②最終文のself.cursor.execute('update analysis_results set search_time =now(), analysis_result = 1, updated_at =now()') #% str(decjson ["positives"])
取り敢えずanalysis_result = 1のように指定した数を代入するとエラーを吐かずに実行できます。

ですがそれと共にコメントアウトしてある str(decjson ["positives"])を付けるとまたエラーを吐かれます。 具体的にpositivesにはVirustotalにて不正だと検知された数が入ります。
この部分はPython2だと機能していたのですがその後Python3に移行したのでその際に2から3に変換する2To3を使って変換しました。

self.cursor.execute('update analysis_results set search_time =now(), analysis_result = 1, updated_at =now()') % str(decjson ["positives"])
TypeError: list indices must be integers or slices, not str
エラー文自体はStr型だと無理だということらしいです。
Strを外しても同様のエラーを吐かれます。

該当のソースコード

```ここに言語を入力 import json as _json import urllib.request, urllib.parse, urllib.error import urllib.request, urllib.error, urllib.parse import sys import time import mysql.connector import datetime import pprint from urllib.request import Request, urlopen #Apikeyを設定 class Apikey: def __init__(self): #database接続 self.connect = mysql.connector.connect(user='root', password='', host='localhost', database='kaiseki_development', charset='utf8') self.connect.autocommit = True self.cursor = self.connect.cursor() self.cursor.execute('use kaiseki_development') #virustotal_api_keysの中身を空に self.cursor.execute('truncate table virustotal_api_keys') #apikey def set_apikeys(self): apikeys = [ apikeyが入ってます。] for n in range(len(apikeys)): #table virustotal_api_keysのapi_key,use_time,use_numbers,created_at,updated_atに追加 self.cursor.execute('insert into virustotal_api_keys(api_key,use_time,use_numbers,created_at,updated_at) values(%s,now(),0,now(),now())' % (apikeys[n])) #Analysisを設定 class Analysis: def __init__(self,analysis_id): #database接続 self.connect = mysql.connector.connect(user='root', password='', host='localhost', database='kaiseki_development', charset='utf8') self.connect.autocommit = True self.cursor = self.connect.cursor(buffered=True) self.analysis_id = analysis_id self.cursor.execute('use kaiseki_development') self.analyse_url = "https://www.virustotal.com/vtapi/v2/url/scan" def virustotal(self): self.url = str(self.cursor.execute('select short_url from short_urls where id = + %d' % (self.analysis_id))) #現在の時間 now = datetime.datetime.now() self.cursor.execute('select Max(id) from virustotal_api_keys') record = self.cursor.fetchone() mMax = record[0] #idの最大値をVirustotal_api_keysから取得 for m in range(mMax): #now.minuteとuse_timeが一緒 self.cursor.execute('select use_time from virustotal_api_keys where id = %d' % (m+1)) if str(now.minute) == str(record[0]): #この分に使った回数が4回かrecord = self.cousor.fetchone() self.cursor.execute('select use_numbers from virustotal_api_keys where id = %d ' % (m+1)) record = self.cursor.fetchone() if int(record[0]) == 4: #今見ているidが最大値を満たしているか if m + 1 == mMax: time.sleep(60) #sleepしたらidの探索を元に戻す m = -1 continue else: break else: self.cursor.execute('update virustotal_api_keys set use_numbers = 0 where id = %d' % (m+1)) break self.cursor.execute('select api_key from virustotal_api_keys where id = %d' % (m+1)); record = self.cursor.fetchone() self.apikey = str(record[0]) self.__calc() #table virustotal_api_keysのuse_time,use_numbersにnow,use_number+1をして格納 self.cursor.execute('update virustotal_api_keys set use_time = now(),use_numbers = use_numbers + 1 where id = %d' % (m+1)) def __calc(self): targeturl = self.url url = self.analyse_url apikey = self.apikey parameters = urllib.parse.urlencode({"apikey": apikey,"targeturl": self.url}).encode("utf-8") response = urllib.request.urlopen("https://www.virustotal.com/vtapi/v2/url/scan", data=parameters) json = _json.loads(response.read().decode('utf-8')) pprint.pprint(json) if not json: print("Error in calling /url/scan API") return 3 scan_id = json["scan_id"] print("Wait 10 seconds...") time.sleep(10) print("Waiting response 'GET /url/report'") query = urllib.parse.urlencode({"apikey": self.apikey, "resource": scan_id}) response = urllib.request.urlopen("https://www.virustotal.com/vtapi/v2/url/report?" + query) json = _json.loads(response.read().decode('utf-8')) pprint.pprint(json) #print (["positives"]) if not json: print("Error in calling /url/report API") return 4 return 0 if __name__ == "__main__": sys.exit(main()) #print (["positives"]) #m2 = "url" #print(decjson["m2"]) #self.cursor.execute('update analysis_results set search_time =now(), analysis_result = %s, updated_at =now()' % str(decjson ["positives"]))

補足情報(FW/ツールのバージョンなど)

Python3.5
mysql-connector-python
データベース自体はMariaDBを使っています

もしもSQL文において変数出力の書き方が間違っている場合どのように修正したらよいか教えていただきたいです。どうかよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

括弧の位置がおかしいのですが、こうじゃないですか?

self.cursor.execute('update analysis_results set search_time =now(), analysis_result = %s, updated_at =now()' % str(decjson["positives"]))

投稿2018/03/21 11:07

編集2018/03/21 11:10
yukkeorg

総合スコア985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yukkeorg

2018/03/21 11:14

なお、可能な限り安全に実行するため、SQL文の動的な作成には ? を使ったパラメータ割当機能を利用することをおすすめします。
peromaron

2018/03/21 11:53

上記のように変更してみましたが同様のエラーを吐かれてしましました… ?を使ったパラメータ割り当て機能については知らなかったので調べてみます!!
yukkeorg

2018/03/21 13:33

私の提案した内容は、エラーが発生するとしても同じエラーにはならないはずですが、どこをどう変えて、どのようなエラーが出たのでしょうか?
peromaron

2018/03/21 15:20

いえ、教えていただいた所を修正したところ同様の self.cursor.execute('update analysis_results set search_time =now(), analysis_result = %s, updated_at =now()' % str(decjson["positives"])) TypeError: list indices must be integers or slices, not str が出てきます。
yukkeorg

2018/03/21 15:30

なるほど... もう一つ教えてください。 エラーが出る前の行で print(decjson) とするとどのように表示されますか?
yukkeorg

2018/03/21 15:33

といいますのも、もう少し細かく確認してみましたら、decjsonがdict型ではなくlist型の可能性があることに気づいたためですが、いかがでしょうか。
peromaron

2018/03/22 13:31

print(decjson)とすると [] analysis_results updated at id = 2610 と出てきます。[]が気になりますがエラーは恐らく吐いてないです…❓ ちなみに最終行をコメントアウトせずにprint(decjson)を入れるとprintされずに先程同様のエラーが出てきます。
yukkeorg

2018/03/22 14:50

VirusTotalに実際に加入してみて動作を確認してみました。 APIのドキュメントもみてみました。2つ指摘部分があります。 1つめは/url/scanの呼出しについてですが、指定しなければ行けないパラメータは、resouceではなくurlです。多分結果が[]なのは、APIの呼び出し方法が間違っているからだと思います。(ちなみに [] をjson.loadsにかけると空のリストになります。) 2つめは、/url/scanは指定したURLのスキャンをキューイングするだけで、結果は/url/reportで得る必要があります。結果として得たい positives は、/url/reportの結果に含まれています。
peromaron

2018/03/23 14:03 編集

なるほど。わざわざ本当にありがとうございます… Apiの呼び出し方が恐らく間違っているとの事でしたので一応全てのプログラム内容をこちらに貼り付けさせていただきます。 具代的には api_key.py 自体は行えておりApiをデータベースに格納できているのは確認済みです。 その後analysis.pyを呼び出す時に python analysis.py ○○ この○の部分に第二引数を渡すと返ってくるようにしてあります。
yukkeorg

2018/03/23 13:39

VirusTotalの URLスキャン APIについて簡単にプログラムを作ってみました。 https://gist.github.com/yukkeorg/43de0c7cce8c3ab0773590ae23a18f72 実行方法についてはソースコードの上の方にコメントで記載します。 あと、公開されていたプログラムを確認しましたが、APIKEYは利用者が秘密にしておかなければならない情報ですので、削除されたほうが良いかと思います。
peromaron

2018/03/23 15:47 編集

本当にありがとうございます…。 実際に試させていただいたのですがVT_APIKEYに実際のapikeyを入力して実行してみましたが Can not read 〇〇(入力したapikey)environment variable とエラーを吐かれてしまいます…。 僕の方でもプログラムを教えていただいたものを少し組み込んでみました(本文のプログラムを修正しました)が、確かにおっしゃる通り [] Error in calling /url/scan API analysis_results updated at id = 〇〇 のように[]が出てきてしまい、Apikeyを取得出来てないと思いました。ただ何故apikeyが取得出来ていないかが不明です…。 やはりデータベースには格納できていたので接続自体は行えてるはずなのですがそこから取得出来てないのかなと思ってます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問