利用者:IAX86/エスケープ転載ツール (GUI版)

出典: 謎の百科事典もどき『エンペディア(Enpedia)』
ナビゲーションに移動 検索に移動
動作UI

以前日記で書いたように、エスケープ転載ツールを雑ながらGUI化しました。

本家からの変更点[編集]

  • まずCUIで、環境によってはソースがコピーしにくい
→ 以前の改変版同様、ソースは勝手にクリップボードへコピーするようにしました。
  • 起動が面倒くさい (コマンドプロンプト → python escape.py)
→ 下準備次第で、exe単体でも起動できるようになります (言ってしまえばCUI版も可能だが)
  • 要約をもう一度コピーする必要がある
→ index.phpのsummary変数で自動挿入できるようにしました。
  • 要約の手直しが必要な場合が多い (削除依頼テンプレート除去だけでも「エスケープ転載の上テンプレート除去…。」)
→ 削除依頼・スタブテンプレート除去だけならチェックボックス一つで変更できるようにしました。

当然ながら、本家さんリスペクトです。

スクリプト[編集]

あまりにも長いので折っています
 

# coding: UTF-8
'''
スクリプトの詳細はhttps://enpedia.rxy.jp/wiki/%E5%88%A9%E7%94%A8%E8%80%85:IAX86/%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E8%BB%A2%E8%BC%89%E3%83%84%E3%83%BC%E3%83%AB_(GUI%E7%89%88) 参照
Licenses:
    * CC BY-SA 3.0
    * CC BY-SA 4.0
Developing Enviroment:
    * Windows 8.1 (6.3.9600) 64bit
    * Python 3.11.4
'''

'''
↓ 変更前データ (ライセンス行除去済み)
-------------------------------------------------------------------------------
 Author:      WxYuki
 Created:     24/09/2022
 Copyright:   (c) WxYuki 2022
-------------------------------------------------------------------------------
↑ 変更前データ
 Modified by:IAX86
 Modified point: functionalization, split configuration, comment out with three quotations
 Copied from: 
https://enpedia.rxy.jp/wiki/%E3%82%88%E3%81%BF%E3%82%82%E3%81%AE:Python%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E8%BB%A2%E8%BC%89%E3%83%84%E3%83%BC%E3%83%AB%E3%81%AE%E6%84%9F%E6%83%B3%E3%81%AA%E3%81%A9
元ライセンスはCC BY-SA 3.0
元スクリプトと改変の情報終わり
'''

### LIBRARIES ###
import requests
from urllib.request import Request, urlopen
from urllib.parse import urlencode
from urllib.error import URLError, HTTPError
import json
import tkinter as tk # Tkinter、GUIライブラリ
import tkinter.ttk as ttk # Tkinterの内部ライブラリ、WinでのGUIが9x風じゃなくなる
import webbrowser as wb # Webbrowser、ブラウザを開くライブラリ
import pyperclip as clip # Pyperclip、クリップボード管理ライブラリ

### GLOBAL VAR DEFINATION ###
global wpbaseurl, wpapiurl, wparticleurl, epurl, copysummary, status, templateremoved # ここで一応定義しておくグローバル変数

### VAR DEFINATION ###
wpbaseurl = "https://ja.wikipedia.org/"
wpapiurl = wpbaseurl + "w/api.php"
wparticleurl = wpbaseurl + "wiki/"
epurl = "https://enpedia.rxy.jp/wiki/"


def escape(article): # インデント入れまくって関数化したCUI版のソース
    S = requests.Session()
    URL = wpapiurl
    in_title = article
    Article_PARAMS = {
        "action":"query",
        "prop":"revisions",
        "titles":in_title,
        "rvprop":"content",
        "format":"json"
    }

    #記事ゾーン
    Article_R = S.get(url=URL,params=Article_PARAMS)
    Article_DATA =Article_R.json()
    #print(Article_DATA)
    #get->jsonで読み込みの流れ

    #IDぞーん
    AF_ID = Article_DATA["query"]["pages"].keys()
    ID = str(AF_ID).lstrip("dict_keys(['(").rstrip("'])")

    content = str(Article_DATA["query"]["pages"][ID]["revisions"][0]["*"])#記事

    #履歴ゾーン
    HISTORY_PARAMS = {
         "action":"query",
        "prop":"revisions",
        "titles":in_title,
        "rvprop":"timestamp",
        "format":"json"
    }

    Article_history_R = S.get(url=URL,params=HISTORY_PARAMS)
    Article_history_DATA = Article_history_R.json()

    time_stamp = Article_history_DATA["query"]["pages"][ID]["revisions"][0]["timestamp"]

    #利用者ゾーン
    USERS_PARAMS ={
        "action":"query",
        "prop":"revisions",
        "rvprop":"user",
        "format":"json",
        "titles":in_title,
        "rvlimit":"max"
    }

    USERS_R = requests.get(url=URL,params=USERS_PARAMS)
    USERS_DATA = json.loads(USERS_R.text)

    user_list = []
    for page in USERS_DATA["query"]["pages"].values():
        if "revisions" in page:
            for revision in page["revisions"]:
                if "user" in revision:
                    user_list.append(revision["user"])

    # 重複した利用者名を削除する
    user_list = list(set(user_list))

    user_result = ",".join(map(str, user_list))#利用者

    global summarytext # ここでグローバル化しないとデータが正常に出力されない

    if templateremoved.get() == False:
        summarytext = "[[jawp:{}]]の{}(UTC)の版より全文をエスケープ転載。投稿者:{}。".format(in_title,time_stamp,user_result)
        return(content)
    else:
        summarytext = "[[jawp:{}]]の{}(UTC)の版より全文をエスケープ転載の上不要テンプレート除去等微修正。投稿者:{}。".format(in_title,time_stamp,user_result)
        return(content)

### こっからは完全オリジナル ###
def openwp():
    wb.open(wparticleurl + articlename.get())

def openafd():
    wb.open(wparticleurl + "Wikipedia:削除依頼/ログ/今週")

def openep():
    wb.open(epurl + articlename.get())

def runescape():
    runcui.configure(state="disabled")
    articlename.configure(state="readonly")
    articlename.unbind('<Return>', an_bindid)
    chsummary.configure(state="disabled")
    try:
        src = escape(articlename.get()) # KeyErrorが想定されるのでTry文でエラーが起きても中断されないように
    except KeyError: # エラー処理部、statusにエラーメッセージを出力する
        status.configure(state="normal") 
        status.delete(0, tk.END)
        status.insert(tk.END, "指定した記事が存在しないか、すでに削除されています")
        status.configure(state="readonly")
        reset(0)
    else: # なんともなかったらstatusに成功出力とクリップボードへのソースコピー
        clip.copy(src)
        copysummary.configure(state="normal")
        status.configure(state="normal")
        status.delete(0, tk.END)
        status.insert(tk.END, "ソースをクリップボードへコピーしました")
        status.configure(state="readonly")

def openwithsummary():
    wb.open(url=epurl + articlename.get() + "?action=edit&summary=" + summarytext)
    '''status.configure(state="normal") # 開発版でクリップボードへ要約テキストを出力していた遺構、三連引用符でコメント化
    status.delete(0, tk.END)
    status.insert(tk.END, "要約欄テキストをクリップボードへコピーしました")
    status.configure(state="readonly")'''

def runescaperedir(event): # キー入力を拾ってエスケープの本体スクリプトへ転送するだけ
    runescape()

def reset(resetstatus = 1): # リセットボタンの動作
    global an_bindid, summarytext
    if resetstatus != 0:
        status.configure(state="normal")
        status.delete(0, tk.END)
        status.configure(state="readonly")
    copysummary.configure(state="disabled")
    runcui.configure(state="normal")
    articlename.configure(state="normal")
    an_bindid = articlename.bind('<Return>', runescaperedir)
    chsummary.configure(state="normal")
    summarytext = None

### Tkinter初期化部 ###
root = tk.Tk()
root.title("エスケープ転載ツール (GUI版)")
root.resizable(0, 0)
frame = ttk.Frame(root)
frame.grid(column=0, row=0, padx=5, pady=10)

### ボタン変数初期化部 ###
templateremoved = tk.BooleanVar()
templateremoved.set(True)

### ボタン・テキストボックス・ラベル等設定部 ###
label1 = ttk.Label(frame, text="記事名:")
label2 = ttk.Label(frame, text="状態:")
articlename = ttk.Entry(frame)
an_bindid = articlename.bind('<Return>', runescaperedir)
status = ttk.Entry(frame, state="readonly", width=37)
viewafd = ttk.Button(frame, text="今週分の削除依頼", command=openafd)
checkarticle1 = ttk.Button(frame, text="Wikipediaの当該記事を開く", command=openwp)
checkarticle2 = ttk.Button(frame, text="Enpediaの当該記事を開く", command=openep)
runcui = ttk.Button(frame, text="指定した記事をエスケープ転載", command=runescape)
copysummary = ttk.Button(frame, text="要約を自動入力して編集画面を開く", state="disabled", command=openwithsummary)
chsummary = ttk.Checkbutton(frame, text="テンプレート除去等微修正を前提として要約を生成\n(エスケープ転載ボタンより先に選択)", variable=templateremoved, offvalue=False, onvalue=True)
resetbutton = ttk.Button(frame, text="リセット", command=reset)

### 配置部 ###
label1.grid(row=0,column=0)
articlename.grid(row=0,column=1)
viewafd.grid(row=0, column=3)
chsummary.place(x=200,y=5) # Gridにすると上下幅がずれるのでここだけplace (座標型)
checkarticle1.grid(row=1,column=3)
checkarticle2.grid(row=2, column=3)
runcui.grid(row=1, column=1)
copysummary.grid(row=2, column=2)
label2.grid(row=3,column=1)
status.grid(row=3,column=2)
resetbutton.grid(row=3,column=3)

root.mainloop() # ウインドウを開く

使い方 (Windows)[編集]

  1. Tkinterが入っているか確認してください。(python -m tkinterで謎の窓が出てくればOK)
  2. 本体スクリプトを保存してください。
  3. 必要ライブラリ群 (requests,pyperclip,webbrowser) をインストールしてください。 (pip install requests pyperclip webbrowser or python -m pip install requests pyperclip webbrowser)
  4. ファイルのある場所を開き、python <スクリプトファイル>で実行

使い方 (Linux)[編集]

基本はWinと変わりませんが、

  • TkinterがPythonに内蔵されません。各OSで提供されているパッケージ (Debianならpython3-tk)をインストールしてください。
  • 実行コマンドがpythonではなくpython3です。

単体で実行可能にする (Windows)[編集]

デスクトップやスタートメニューのショートカットにする場合に有用です。ロゴの変え方などについてはGoogleとお友達になってください。Linuxは検証できないので書きません。

  • PyInstallerをインストールします (pipでpyinstaller)
  • ファイルかディレクトリにまとめます。
  • ディレクトリ:pyinstaller -w <スクリプトファイル>
→ 「実行したディレクトリの中のdistの中のスクリプト名の中」(スクリプトのあるディレクトリに現れるdistの中にあるスクリプト名のディレクトリ、圧倒的説明下手)にある全ファイル達をそのまま好きな場所に移し、スクリプト名.exeを実行すると動きます。
  • 一ファイル[1]:pyinstaller -w --onefile <スクリプトファイル>

操作[編集]

  1. 記事名の右のテキストボックスに記事名を入れます。
  2. 「指定した記事をエスケープ転載」をクリックするか、そのままEnterをッターンします。
  3. 2〜3秒フリーズしたのち、状態欄に「ソースをクリップボードへコピーしました」と出れば第一段階は正常終了です。
  4. 「要約を自動入力して編集画面を開く」をクリックすると、自動生成した要約を入力した状態で記事の編集画面を開きます。ソースを貼り付け、ソースと要約を適宜修正していただければ終わりです。

以下、追加機能・エラー等。

  • 「テンプレート除去を前提として要約を生成」にチェックを入れた状態 (デフォルトでON) で動かすと、削除依頼テンプレート・スタブテンプレートの除去が入っても要約を修正する必要がなくなります。
  • 間違った記事をエスケープした場合、
  • 存在しない記事は状態欄にエラーが出るはずです。
  • 存在する記事はそのままエスケープされます。右下のリセットを押すと再度エスケープボタンが押せるようになります。
  • 右上「今週分の削除依頼」から、jawp:Wikipedia:削除依頼/ログ/今週へ飛べます。
  • 右中央「Wikipediaの記事を開く」「Enpediaの記事を開く」から、記事名を入力した状態であればその記事へ飛べます。今考えてみるとEPの方は最終的に要約を生成して開くから遺構と化すかもしれない。
  • 閉じる際は普通に×をクリックで閉じられます。拡大縮小はできません。

仕様[編集]

  • 実際のところ、CUI版を関数化(def)して、関連関数を作り、それをTkinterの操作に割り当てただけです。
  • GUIライブラリはTkinterです。他のでやると開発環境整備やプログラム構築段階でどこかしら上手く行きませんでした。

脚注[編集]

  1. 検証していませんが、こういう場合は大抵起動がめちゃ遅くなります。特に理由がない限りディレクトリ推奨。