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

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

ただいまの
回答率

90.51%

  • Python 3.x

    9794questions

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

  • SQL

    3010questions

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

  • MariaDB

    378questions

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

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

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 434

peromaron

score 1

 前提・実現したいこと

仮想上で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文において変数出力の書き方が間違っている場合どのように修正したらよいか教えていただきたいです。どうかよろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+2

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/21 20:14

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

    キャンセル

  • 2018/03/21 20:53

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

    キャンセル

  • 2018/03/21 22:33

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

    キャンセル

  • 2018/03/22 00: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 が出てきます。

    キャンセル

  • 2018/03/22 00:30

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

    キャンセル

  • 2018/03/22 00:33

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

    キャンセル

  • 2018/03/22 22:31

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

    キャンセル

  • 2018/03/22 23:50

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

    キャンセル

  • 2018/03/23 16:01 編集

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

    キャンセル

  • 2018/03/23 22:39

    VirusTotalの URLスキャン APIについて簡単にプログラムを作ってみました。
    https://gist.github.com/yukkeorg/43de0c7cce8c3ab0773590ae23a18f72
    実行方法についてはソースコードの上の方にコメントで記載します。

    あと、公開されていたプログラムを確認しましたが、APIKEYは利用者が秘密にしておかなければならない情報ですので、削除されたほうが良いかと思います。

    キャンセル

  • 2018/03/24 00:46 編集

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

    キャンセル

同じタグがついた質問を見る

  • Python 3.x

    9794questions

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

  • SQL

    3010questions

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

  • MariaDB

    378questions

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