※この記事はブログ主が途中まで書いたまま半年以上放置されていました。
ニコニコ動画でPSO2動画コンテストというのが開催中だが、投稿作品はタグで探す形式になっている。このため関係ない動画にタグが張られるだけで目当ての動画が探しにくくなるので、自分でちゃんとした動画だけを選別して簡単にまとめられるCGIスクリプトを書いた。サイトは以下のような感じ。
LAMP環境での開発初めてなので、非常にお見苦しいですが・・・
(先輩に15年位前のWebアプリかな?って言われたw)
学生時代にLAMP環境でWebアプリ作りましたという実績が欲しかったってのも作った理由。
特徴
管理画面で動画のID+動画のカテゴリ(5種類固定)を入力して登録すると、サイトに追加され、カテゴリ検索一覧に表示されるようになる。またサイト内で動画再生もできる。
概要
サイトについて
トップページには、サイト内の各カテゴリの動画の一覧ページorキーワードで検索した結果の一覧ページへのリンクがある。一覧ページからは、サイト内の動画再生ページもしくはニコニコ動画の再生ページへ飛べる。
動画とサムネイルなどはニコニコ動画の埋め込みスクリプトを使っている。
動画の追加・削除

管理画面で動画のID(sm以下の番号)を入力しカテゴリを選択、追加or削除をチェックするだけで動画を追加できる。
送信すると、ニコニコAPIを使ってIDから動画名を取得し、データベースにID,カテゴリ、動画名の3つを追加する。
使用したもの
HTMLテンプレート、画像
埋め込みスクリプト
ここ参照↓
システム周り
ほぼ自作。コアサーバー上で、Python+SQLiteで動かしている。Pythonの動作にはhtaccessでadd-handlerの設定が必要だった。
ソースコード
デザイン部分は配布元のものなので省略。
エラー処理?なにそれおいしいの?
index.html(トップページ)の抜粋
<h2>応募動画(部門別)</h2>
<p>
<li><a href="category.py?bu=1&nn=おもしろ動画部門">おもしろ動画部門</a>
<li><a href="category.py?bu=2&nn=スーパープレイ動画部門">スーパープレイ動画部門</a>
<li><a href="category.py?bu=3&nn=ロビアク動画部門">ロビアク動画部門</a>
<li><a href="category.py?bu=4&nn=サウンド動画部門">サウンド動画部門</a>
<li><a href="category.py?bu=5&nn=解説動画部門">解説動画部門</a>
</p>
<h2>動画を検索</h2>
<p> 1キーワードでの検索のみ対応しています。(半角スペース区切りなどは無効)
<form action="search.py" method="post">
キーワード:<input type="text" name="kwd" >
<input type="submit">
</form><br>
カテゴリの動画への一覧へは、部門の番号と部門名をURLのクエリで渡している(カテゴリページでカテゴリ番号からカテゴリ名に直して表示するのがめんどいので)。カテゴリ一覧ページでは、
検索結果一覧ページへは、検索キーワードのみを渡している。
category.py(カテゴリごとの一覧を表示するページ)
#! /usr/local/bin/python
# -*- coding:utf-8 -*-
import sqlite3,os,cgi,sys
print "Content-Type: text/html;charset=UTF-8"
print
reload(sys)
sys.setdefaultencoding('utf-8')
code1="""
<iframe width="312" height="240" src="https://ext.nicovideo.jp/thumb/sm
"""
code2="""
" scrolling="no" style="border:solid 1px #ccc;" frameborder="0"><a href="movie.py?id=
"""
code3="""
">
"""
code4="""
</a></iframe>
"""
qu=cgi.parse_qs(os.environ["QUERY_STRING"])
con = sqlite3.connect("data/data.db")
sql=u"select id,title from movie where bu = ?"
sql_v=[qu["bu"][0]]
print_l=""
for s,t in con.execute(sql,sql_v):
print_l+=code1+str(s)+code2+s+code3+t+code4
print_l+="<a href=\"movie.py?id="+s+"\">"+"このサイトで見る"+"</a><br>"
con.close()
print "<h2>"+qu["nn"][0]+"</h2>"
print """
<p><center>
<a href="javascript:history.back()">前のページに戻る</a>
</center></p>
"""
print print_l
print """
<br>
<p><center>
<a href="javascript:history.back()">前のページに戻る</a>
</center></p>
"""
movie.py(個別の動画を表示するページ)
#! /usr/local/bin/python
# -*- coding:utf-8 -*-
import sqlite3,urllib,os,cig,sys
#デフォルトエンコード変更。これしないとエンコードエラーが起きる
reload(sys)
sys.setdefaultencoding('utf-8')
#とりあえず先に表示しないとエラーが起きそうで怖い
print "Content-Type: text/html;charset=UTF-8"
print
#動画埋め込みスクリプトを4分割したもの。間に動画の情報を入れる。
code1="""
<script type="application/javascript" src="https://embed.nicovideo.jp/watch/sm
"""
code2="""
/script?w=640&h=360"></script><noscript><a href="http://www.nicovideo.jp/watch/sm
"""
code3="""
">
"""
code4="""
</a></noscript>
"""
#URIクエリから動画ID取得
qu=cgi.parse_qs(os.environ["QUERY_STRING"])
#IDをもとにタイトルをデータベスから取得
con = sqlite3.connect("data/data.db")
cur=con.cursor()
sql=u"select title from movie where id =?"
cur.execute(sql,[qu["id"][0]])
s=cur.fetchall()[0][0]
con.close()
#動画プレイヤー表示
print "<h2>"+s+"</h2>"
print "<center>"+code1+qu["id"][0]+code2+qu["id"][0]+code3+s+code4+"</center>"
print """
<br>
<p><center>
<a href="javascript:history.back()">前のページに戻る</a>
"""
search.py(検索結果を表示するページ)
#! /usr/local/bin/python
# -*- coding:utf-8 -*-
import sqlite3,urllib,cgi,sys
#エンコード変更
reload(sys)
sys.setdefaultencoding('utf-8')
print "Content-Type: text/html;charset=UTF-8"
print
code1="""
<iframe width="312" height="240" src="https://ext.nicovideo.jp/thumb/sm
"""
code2="""
" scrolling="no" style="border:solid 1px #ccc;" frameborder="0"><a href="movie.py?id=
"""
code3="""
">
"""
code4="""
</a></iframe>
"""
p=cgi.FieldStorage()
#フォームからキーワードを取得して、データベースから該当動画のIDとタイトル取得
con = sqlite3.connect("data/data.db")
cur=con.cursor()
sql=u'select id,title from movie where title like "%s"' % ("%" + p.getvalue("kwd") + "%")
cur.execute(sql)
infom=cur.fetchall()
con.close()
#h2を表示
print "<h2>"+p.getvalue("kwd")+"</h2>"
print_l=""
#検索結果をループで追加していく
for p,q in infom:
print_l+="<br>"+code1+p+code2+p+code3+q+code4
print_l+="<a href=\"movie.py?id="+p+"\">"+"このサイトで見る"+"</a>"
#結果を表示
print print_l
add.py(動画の追加・削除の管理ページ)
#! /usr/local/bin/python
# -*- coding:utf-8 -*-
print """
Content-Type: text/html;charset=UTF-8"
<body>
<form action="add2.py" method="post">
<p>部門:
<li>おもしろ(1)<input type="radio" name="bu" value="1" />
<li>スーパープレイ(2)<input type="radio" name="bu" value="2" />
<li>ロビアク(3)<input type="radio" name="bu" value="3" />
<li>サウンド(4)<input type="radio" name="bu" value="4" />
<li>解説(5)<input type="radio" name="bu" value="5" /></p>
<p>ID:<input type="text" name="id" />
<p>追加:<input type="radio" name="ad" value="add" checked/>
削除:<input type="radio" name="ad" value="delete"/>
<p><input type="submit"/>
</form>
</body>
</html>
"""
import sqlite3,requests,cgi,xml.etree.ElementTree as ET
p=cgi.FieldStorage()
#追加の場合、すでに追加されていないことを確認して
if p.getvalue("id")!=None:
url="http://ext.nicovideo.jp/api/getthumbinfo/sm"
response = requests.get(url+p.getfirst("id"))
root = ET.fromstring(response.content)
sss=0
q=root[0][1].text
con=sqlite3.connect("data.db")
cur=con.cursor()
if p.getvalue("ad")=="add":
sql="insert into movie (id,bu,title) values (?,?,?)"
sql_v=(p.getvalue("id"),p.getvalue("bu"),q)
cur.execute("select * from movie where id=?",[p.getvalue("id")])
if len(cur.fetchall())!=0:
sss=1
elif p.getvalue("ad")=="delete":
sql=u"delete from movie where id=?"
sql_v=[p.getvalue("id")]
#エラーの場合
if p.getvalue("ad")=="delete" or (p.getvalue("ad")=="add" and p.getvalue("bu")!=None and sss==0):
cur.execute(sql,sql_v)
con.commit()
print "success on sm"+p.getvalue("id")
else:
print "error"
con.close()
(他にSQLiteのデータベースファイルとCSSファイル)

コメント