pythonでYoutube動画のタイトルと概要欄を取得
YouTube Data API の概要 | Google Developers
Youtube Data APIを使えば、Youtubeから様々な情報を取得できる。
以下にその例を示した。
①Youtubeの動画のidを使って、その動画のタイトルを得る。
(ソースコード)
import requests id='z9WHIkedhz8' apikey='(Youtube Data api のキー)' url = 'https://www.googleapis.com/youtube/v3/videos?id='+id+'&key='+apikey+'&part=snippet,contentDetails,statistics,status' response = requests.get(url) # print(response.json()) print("https://www.youtube.com/watch?v="+response.json()['items'][0]['id']) print(response.json()['items'][0]['snippet']['title'])
(実行結果)
> python .\title.py https://www.youtube.com/watch?v=z9WHIkedhz8 【改名はまさかの…】結局誰が一番球技上手いの? 第1回球技王!【後編】
②同様にして概要欄の文章を取得することもできる。
(ソースコード)
print(response.json()['items'][0]['snippet']['description'])
(実行結果)
> python .\title.py 撮影協力:岡崎市 https://fc.okazaki-kanko.jp/news/94 今回の企画では「球技」とひとくくりにしていろいろなスポーツで遊びましたが、よく考えてみればなんか「球」を使う競技多いですよね。流行ってるんですか? 「スポーツなんだから球使うだろ」「球じゃないとくちゃくちゃになるだろ」とお思いかもしれませんが、本当にそうですか?ラグビーやアメフトは意味わかんない形のボール使ってますし、バドミントンやインディアカも意味わかんない羽根使ってます。でも別にスポーツとして成立してますよね?むしろその形状ならではの特徴的な動きが生まれていていい感じです。 : : : ゆめまる→https://twitter.com/TO_yumemarucas 虫眼鏡→https://twitter.com/TO_ZAWAKUN
③チャンネルidを使って、そのチャンネルの動画のタイトルを得る。
(ソースコード)
import requests channelid='UCutJqz56653xV2wwSvut_hQ' apikey='(Youtube Data api のキー)' url = 'https://www.googleapis.com/youtube/v3/search?key='+apikey+'&channelId='+channelid+'&part=snippet,id&order=date&maxResults=1' response = requests.get(url) # print(response.json()) print("https://www.youtube.com/watch?v="+response.json()['items'][0]['id']['videoId']) print(response.json()['items'][0]['snippet']['title'])
urlのchannelIdでチャンネルを指定、maxResultsで出力する結果の数を指定。
(実行結果)
> python .\channel.py https://www.youtube.com/watch?v=vn50D0NEpg4 【りょうやん】みんなの「お前おかしいよ!」っていう5対1を見つけ合おう!!!
そのチャンネルの最新の動画が表示される。
④maxResultsを変えて、タイトルの一覧を表示する。
(ソースコード)
import requests channelid='UCutJqz56653xV2wwSvut_hQ' apikey='(Youtube Data api のキー)' url = 'https://www.googleapis.com/youtube/v3/search?key='+apikey+'&channelId='+channelid+'&part=snippet,id&order=date&maxResults=50' num=1 response = requests.get(url) for i in range(50): print(str(num)+'. '+response.json()['items'][i]['snippet']['title']) num+=1
(実行結果)
> python .\channel.py 1. 【りょうやん】みんなの「お前おかしいよ!」っていう5対1を見つけ合おう!!! 2. 【改名はまさかの…】結局誰が一番球技上手いの? 第1回球技王!【後編】 3. 【最下位は改名】結局誰が一番球技上手いの? 第1回球技王!【前編】 4. 【46道府県旅行の旅!滋賀県編】〜黄昏の湖、道化師の鎮魂歌〜 : : 46. 【鍛冶屋】それは無理だろって素材だけで刃物作り対決!!! 47. 【バカ商品】東海オンエアショッピングへようこそ!!!! 48. 1日全力で努力したらどれだけの数のYouTuberとコラボできるの!? 49. 野球の道具を野球以外に使って新競技を考えてみよう! 50. 【猛火】1000円以内で自分の財布を「防火仕様」にしよう!
⑤51以上の動画のタイトルを表示する。
maxResultsは50までしか指定できないので、複数回リクエストを送る。
import requests channelid='UCutJqz56653xV2wwSvut_hQ' apikey='(Youtube Data api のキー)' url = 'https://www.googleapis.com/youtube/v3/search?key='+apikey+'&channelId='+channelid+'&part=snippet,id&order=date&maxResults=50' num=1 response = requests.get(url) for i in range(50): print(str(num)+'. '+response.json()['items'][i]['snippet']['title']) num+=1 for j in range(4): next=response.json()["nextPageToken"] nexturl=url+'&pageToken='+next response = requests.get(nexturl) for i in range(50): print(str(num)+'. '+response.json()['items'][i]['snippet']['title']) num+=1
(実行結果)
> python .\channel.py 1. 【りょうやん】みんなの「お前おかしいよ!」っていう5対1を見つけ合おう!!! 2. 【改名はまさかの…】結局誰が一番球技上手いの? 第1回球技王!【後編】 3. 【最下位は改名】結局誰が一番球技上手いの? 第1回球技王!【前編】 4. 【46道府県旅行の旅!滋賀県編】〜黄昏の湖、道化師の鎮魂歌〜 5. 【超難問】これなんの粉末でしょうクイズでブチギレ必至!!! 6. 【大ブランク】3回転んだら即終了スノボ! 7. 「こんな素材、編集でどうやって使うねん!!」→使います。 8. 【答えは実物で】第一回!現物大喜利!!!!!! 9. 【家庭事情×作品】自宅にある物だけでジオラマ作り対決!!! 10. 【失礼】プロフェッショナルのスゴ業をそんな事に使うな!!選手権 11. 【穴を制せ】負けたらピアスの対決!!穴王!!! 12. 【運×演技力】相談なしで5人の衣装を揃えて即興コントを演じきれ! : : 244. 【過去最悪】全味覚の世界最強を全て混ぜたら本当に死にかけた 245. 【5vs1クイズ対決】虫眼鏡ってさぁ、本当に頭いいの? 246. 【20種以上のフレーバー】俺たちがドクターペッパーを超えたドリンクを作ってやるよ!確かにそう意気込んでいた・・・ 247. 手作りバットで一番遠くにボール飛ばせた奴が勝ち対決!! 248. 【水溜りオンエア】おふざけなしのガチ文理ラップ対決! 249. 【サスペンス】リレー方式でドラマを作ったらまさかの結果に!? 250. 【二遊間】もう一度アライバコンビの超絶プレーが見たいんだ・・・【中日ドラゴンズ】
⑥実用例
chindafalldesu.hatenablog.com
参考
YouTube Data API の概要 | Google Developers
YouTube Data api v3をPythonから使って特定のチャンネルの動画を取得する - Qiita
(間違い等あればコメントよろしくお願いいたします。)
pythonとParamikoでsshの通信を行う(sshサーバ作成)
paramikoモジュールを使ってpythonでsshサーバを立ててみる。
(1)sshサーバを立てる (適宜分割して示す)
import socket import threading import paramiko host_key = paramiko.RSAKey(filename='test_rsa.key')
簡単のため配布されているデモファイル 'test_rsa.key' を使う。
paramiko/test_rsa.key at master · paramiko/paramiko · GitHub
bind_host="0.0.0.0" bind_port=50000 pw="password is 12345\n"
今回はpwの文字列を送ることにする。ポート番号50000を開く。
class Server(paramiko.ServerInterface): def __init__(self): self.event = threading.Event() def check_channel_request(self, kind, chanid): if kind == 'session': return paramiko.OPEN_SUCCEEDED return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED def check_auth_password(self, username, password): if(username=='user') and (password=='pass'): return paramiko.AUTH_SUCCESSFUL return paramiko.AUTH_FAILED # def check_auth_publickey(self, username, key): # if (username=="user") and (key ==(鍵)): # return paramiko.AUTH_SUCCESSFUL # return paramiko.AUTH_FAILED
これでサーバの動作を定義する。
パスワードを使って接続を確立する場合はcheck_auth_password()を使い、鍵を使う場合はcheck_auth_publickey()を使う。
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind((bind_host, bind_port)) sock.listen(5) client, addr = sock.accept()
ソケットを使って通信を確立する。
t = paramiko.Transport(client) t.add_server_key(host_key) server = Server() t.start_server(server=server)
sshトランスポートをソケット通信にアタッチし、セッションを開始し、チャネルを生成する。
chan=t.accept(30) chan.send("Hello\n".encode('utf-8')) chan.send(pw.encode('utf-8'))
クライアントによって開かれた次のチャネルを使って文字列を送信する。
t.close()
セッションを終了し、すべてのチャネルを閉じる。
(2)接続を試す
> ssh -p 50000 user@--------- The authenticity of host '[-------]:50000 ([--------]:50000)' can't be established. RSA key fingerprint is --------- Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[-------]:50000' (RSA) to the list of known hosts. user@-------'s password: (パスワードを入力) Hello password is 12345 Connection reset by ------- port 50000
下記のデモファイルを参考にした。
paramiko/demos at master · paramiko/paramiko · GitHub
(間違い等あればコメントよろしくお願いいたします。)
pythonとtelnetで通信を行う
telnetとsshのどちらもほかのコンピュータと接続するための仕組みであるが、telnetは通信を暗号化しないためその内容を覗き見られる危険性がある。
サーバを自分で作って、wiresharkで通信を覗いてみる。
(1)telnetで通信を行う
・サーバ
import socket import subprocess bind_host="0.0.0.0" bind_port=50000 pw="password is 12345\n" server=socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((bind_host, bind_port)) server.listen(5) print("host: "+bind_host) print("port: "+str(bind_port)) while True: client, addr=server.accept() print("from:"+ addr[0]+" "+str(addr[1])) while True: print("waiting for his response...") rec=client.recv(1024) client.send(pw.encode("utf-8")) if len(rec)==0: client.close() break
・クライアント
telnet 192.168.129.17 50000 Trying 192.168.129.17... Connected to 192.168.129.17. Escape character is '^]'. Connection closed by foreign host. hi password is 12345
クライアントはサーバに接続してメッセージを送るとサーバから "password is 12345" が送られる。
だがこの内容は覗き見られる可能性がある。
(2)Wiresharkで内容を覗く
Wiresharkで上記のサーバとクライアント間の通信を覗くと下記が得られた。
・クライアント側が送った情報
・サーバ側が送った情報
次回はsshで同様のことを行う。
(間違い等あればコメントよろしくお願いいたします。)
ksnctfを使ってHTTP通信について学ぶ④(python・ksnctf-9)
前回、pythonでHTTPリクエストメッセージを作り、HTTPレスポンスメッセージを表示させた。
これを用いて、ksnctfの問9を解いてみる。
ksnctf - 9 Digest is secure!
認証を行ってflag.htmlにアクセスすればいいことまではわかっている。
Authorizationヘッダを付けたHTTPリクエストメッセージをつくって、HTTPレスポンスメッセージを表示させてみる。
①Authorizationヘッダを作る
Authorizationヘッダを作るためにはnonceが必要である。リクエストメッセージを送り、nonceを得る。
ハッシュの作成にはhashlibライブラリを使う。
import requests import hashlib url="http://ctfq.sweetduet.info:10080/~q9/flag.html" nonce = requests.get(url).headers["WWW-Authenticate"].split(" ")[2][7:-2] a1="c627e19450db746b739f41b64097d449" nc="00000001" cnonce="9691c249745d94fc" qop="auth" a2=hashlib.md5(b"GET:/~q9/flag.html").hexdigest() res=hashlib.md5((a1+":"+nonce+":"+nc+":"+cnonce+":"+qop+":"+a2).encode('utf-8')).hexdigest() key='Digest username="q9", realm="secret", nonce="'+nonce+'", uri="/~q9/flag.html", algorithm=MD5, response="'+res+'", qop=auth, nc=00000001, cnonce="9691c249745d94fc"'
②HTTPリクエストメッセージを送る。
前回のコードに上記の認証を加える。
headers={ 'Host': 'ctfq.sweetduet.info:10080', 'Connection':'keep-alive', 'Authorization': key, 'User-Agent': 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Encoding': 'gzip,deflate,sdch', 'Accept-Language': 'ja,en-US;q=0.8,en;q=0.6', 'Accept-Charset': 'Shift_JIS,utf-8;q=0.7,*;q=0.3', } r=requests.get(url, headers=headers)
③HTTPレスポンスメッセージを得る。
print(r.status_code) print(r.headers) print(r.text)
(実行結果)
> python .\sample.py 200 {'Date': 'Tue, 21 Jan 2020 09:56:55 GMT', 'Server': 'Apache/2.2.15 (CentOS)', 'Authentication-Info': 'rspauth="ed70106349d8d9e632ae77641a40a1b7", cnonce="9691c249745d94fc", nc=00000001, qop=auth', 'Last-Modified': 'Sat, 26 May 2012 12:29:31 GMT', 'ETag': '"422e3-90-4c0efa30418d3"', 'Accept-Ranges': 'bytes', 'Content-Length': '144', 'Connection': 'close', 'Content-Type': 'text/html; charset=UTF-8'} <!DOCTYPE html> <head> <meta charset="utf-8"> <title>Q9</title> </head> <body> <p>(フラグ)</p> </body> </html>
下記のドキュメントを参考にした。
Requests: 人間のためのHTTP — requests-docs-ja 1.0.4 documentation
(間違い等あればコメントよろしくお願いいたします。)
ksnctfを使ってHTTP通信について学ぶ③(python・ksnctf-8)
HTTP通信をpythonで行う方法を学び、それを使って次回ksnctfの問9を解く。
ksnctf - 9 Digest is secure!
①HTTPリクエストメッセージをPythonで作る
・下記はksnctfの問8のHTTPリクエストメッセージ
GET /~q8/ HTTP/1.1 Host: ctfq.sweetduet.info:10080 Connection: keep-alive Authorization: Basic cTg6RkxBR181dXg3eksyTktTSDhmU0dB User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip,deflate,sdch Accept-Language: ja,en-US;q=0.8,en;q=0.6 Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.3
・Requestsライブラリを使って、Pythonで同じメッセージを作ってみる
import requests url="http://ctfq.sweetduet.info:10080/~q8/" headers={ 'Host': 'ctfq.sweetduet.info:10080', 'Connection':'keep-alive', 'Authorization': 'Basic cTg6RkxBR181dXg3eksyTktTSDhmU0dB', 'User-Agent': 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Encoding': 'gzip,deflate,sdch', 'Accept-Language': 'ja,en-US;q=0.8,en;q=0.6', 'Accept-Charset': 'Shift_JIS,utf-8;q=0.7,*;q=0.3', } r=requests.get(url, headers=headers)
②HTTPレスポンスメッセージをPythonで表示してみる
・下記はksnctfの問8のHTTPレスポンスメッセージ
HTTP/1.1 200 OK Date: Sat, 26 May 2012 20:54:05 GMT Server: Apache/2.2.15 (CentOS) Last-Modified: Sat, 26 May 2012 12:24:46 GMT ETag: "422da-b8-4c0ef920b3f8e" Accept-Ranges: bytes Content-Length: 184 Connection: close Content-Type: text/html; charset=UTF-8 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Q8</title> </head> <body> <p>Congratulations!</p> <p>The flag is q8's password.</p> </body> </html>
・pythonでメッセージを表示させてみる
(ソースコード)
print(r.status_code) print(r.headers) print(r.text)
(実行結果)
> python .\sample.py 200 {'Date': 'Tue, 21 Jan 2020 08:38:22 GMT', 'Server': 'Apache/2.2.15 (CentOS)', 'Last-Modified': 'Sat, 26 May 2012 12:24:46 GMT', 'ETag': '"422da-b8-4c0ef920b3f8e"', 'Accept-Ranges': 'bytes', 'Content-Length': '184', 'Connection': 'close', 'Content-Type': 'text/html; charset=UTF-8'} <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Q8</title> </head> <body> <p>Congratulations!</p> <p>The flag is q8's password.</p> </body> </html>
下記のドキュメントを参考にした。
Requests: 人間のためのHTTP — requests-docs-ja 1.0.4 documentation
(間違い等あればコメントよろしくお願いいたします。)
pythonでsocketを使って通信を行う③ (コマンドの実行)
今回は前回までのコードを再び改良し、コマンドを実行できるようにする。
準備
コマンドの実行にはsubprocessモジュールを用いる。
下記のようにして、コマンドを実行できる。
import subprocess com=subprocess.run("dir", stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) print(com.stdout.decode('cp932')) print(com.stderr.decode('cp932'))
> python .\30.py ドライブ C のボリューム ラベルは Windows です ボリューム シリアル番号は 40BE-398B です C:\-----------------\02 のディレクトリ 2020/01/12 21:27 <DIR> . 2020/01/12 21:27 <DIR> .. 2020/01/12 21:28 549 30.py 2020/01/12 21:27 24 sample.txt 2 個のファイル 573 バイト 2 個のディレクトリ 5,052,829,696 バイトの空き領域
上記のモジュールを使って前回までのコードを改良する。
ソースコード
・サーバ側
import socket import subprocess bind_host="0.0.0.0" bind_port=50000 server=socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((bind_host, bind_port)) server.listen(5) print("host: "+bind_host) print("port: "+str(bind_port)) while True: client, addr=server.accept() print("from:"+ addr[0]+" "+str(addr[1])) while True: print("waiting for his response...") rec=client.recv(1024) com=subprocess.run(rec.decode('utf-8'), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) # print(rec.decode('utf-8')) client.send(com.stdout) client.send(com.stderr) if len(rec)==0: client.close() break
・クライアント側
import socket target_host="(サーバ側のIPアドレス)" target_port=50000 client=socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((target_host, target_port)) while True: com=input("command: ") client.send(com.encode('utf-8')) rec=client.recv(4096) print(rec.decode('cp932'))
実行結果
・サーバ側
> python .\server.py host: 0.0.0.0 port: 50000 from:(クライアント側のIPアドレス)(クライアント側のポート番号) waiting for his response... waiting for his response... waiting for his response... waiting for his response... waiting for his response... waiting for his response...
・クライアント側
> python .\client.py command: dir ドライブ C のボリューム ラベルは Windows です ボリューム シリアル番号は 40BE-398B です C:\---------------------\01 のディレクトリ 2020/01/12 21:34 <DIR> . 2020/01/12 21:34 <DIR> .. 2020/01/12 21:16 24 02.txt 2020/01/12 21:16 24 sample.txt 2020/01/12 21:14 724 server.py 3 個のファイル 772 バイト 2 個のディレクトリ 5,051,006,976 バイトの空き領域 command: type sample.txt hello i'm from Canada command: copy sample.txt copy.txt 1 個のファイルをコピーしました。 command: dir ドライブ C のボリューム ラベルは Windows です ボリューム シリアル番号は 40BE-398B です C:\---------------------\01 のディレクトリ 2020/01/12 21:34 <DIR> . 2020/01/12 21:34 <DIR> .. 2020/01/12 21:16 24 02.txt 2020/01/12 21:16 24 copy.txt 2020/01/12 21:16 24 sample.txt 2020/01/12 21:14 724 server.py 4 個のファイル 796 バイト 2 個のディレクトリ 5,049,970,688 バイトの空き領域 command: type copy.txt hello i'm from Canada command:
解説
・クライアント側からサーバ側にコマンドを送信し、サーバ側で実行されたコマンドの実行結果をクライアント側に返している。
・クライアント側はこれによってサーバ側のディレクトリの中身、ファイルの中身を見ることができる。
(間違い等あればコメントよろしくお願いいたします。)
pythonでsocketを使って通信を行う② (ファイルの送受信)
今回は前回作ったコードを改良して、テキストファイルを送信できるようにする。
ソースコード
・サーバ側
import socket bind_host="0.0.0.0" bind_port=50000 server=socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((bind_host, bind_port)) server.listen(5) print("host: "+bind_host) print("port: "+str(bind_port)) while True: client, addr=server.accept() print("from:"+ addr[0]+" "+str(addr[1])) while True: print("waiting for his response...") rec=client.recv(1024) fd=open("get.txt", "wb") fd.write(rec) fd.close() print(rec.decode('utf-8')) if len(rec)==0: client.close() break
・クライアント側
import socket target_host="(サーバ側のIPアドレス)" target_port=50000 client=socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((target_host, target_port)) while True: while True: file=input("textfile: ") try: fd=open(file, "rb") except FileNotFoundError: print("can't open this file") print("please try it again") print("") else: text=fd.read() fd.close() break client.send(text) print("succeed") print("")
・送るテキストファイル (send.txt)
hello! my name is Alex
実行結果
・サーバ側
> python .\server.py host: 0.0.0.0 port: 50000 from:(クライアント側のIPアドレス)(クライアント側のポート番号) waiting for his response... hello! my name is Alex waiting for his response...
・クライアント側
> python .\client.py textfile: fdsa can't open this file please try it again textfile: send.txt succeed textfile:
・得られたファイル (get.txt)
hello! my name is Alex
解説
1.サーバ側はクライアント側からの接続を待ち、接続後はデータの送信を待つ。
2. クライアント側はテキストファイル名を入力する。
ファイアウォールの設定等が原因で送れないことがあるので注意。
(間違い等あればコメントよろしくお願いいたします。)