はじめの前のおねがい
できれば「いいね♡」をお願いします。励みになります。
はじめに
このコードはPython 3とPythonista 3に対応しています。ただし、別途request
モジュールなどが必要です。
本コードを実行するとどうなるか
本コードは
- クリップボード内のWikipediaおよびWiktionaryのURLを検知
- ページIDを取得
- ページID参照がされたWikipediaおよびWiktionaryのURLを再コピー
します。その際に、もしも下記の条件の場合、
- 既にIDに変換されている場合 → 「既に変換済みです」を返します
- 該当する記事がない場合 → 「変換不可能なリンクです」を返します
となります。
また、おまけ機能として、そもそもWikipediaおよびWiktionaryのURLではない場合はANSI文字をURLエンコードします。
ページIDの必要性 — このコードのraison dʼêtre
Wikipedia/Wiktionaryの記事には、それぞれIDが振り分けられている
例えば、WikipediaのFrederik Kortlandt先生の記事を考えてみましょう。
Wikipediaの標準的なhttps://en.wikipedia.org/wiki/Frederik_KortlandtというURLは見出し語が分かりやすいように、このようなURLの形で表記して記事が見られるようになっているだけで、実体の記事は1項目に1番号のみが割り振られ、“3064937”のようなID番号として「Wikipedia記事ID」が割り振られており、https://en.wikipedia.org/?curid=3064937という表記は「その記事IDの記事を表示せよ」というものになっています。
これによって、将来的に悪意ある編集者が見出し語を変更したり、あるいは誤表記だったことが分かり見出し語の変更がされ、かつその変更の際「転送の設定がされなかった場合」に、リンク切れになってしまうのを防ぐことができます。
編集者によるタイトル変更での弊害
実際に言語学者“Szemerényi Oszvald”の日本語項目は以前は「オズワルド・セメレーニ」で、2000年代までの言語学の学習者はこの表記で習っていた(現在でも習っている?)ために、彼のWikipedia記事を案内する場合は“https://ja.wikipedia.org/wiki/オズワルド・セメレーニ”のURLでセメレーニの記事を見ることができましたが、悪意ある記事編集者が、
このように転送用の記事を削除してしまった(2024-03-11現在)ために“https://ja.wikipedia.org/wiki/セメレーニ・オスヴァルド”でしか記事が見られなくなっていました。とりあえずこの項目は私の方でリダイレクト用のページを作っておきましたので転送されるようになっていますが(2024-03-12現在)、無論、このようにしてもいつ再び削除されるかは分からないのが現状です。
いうまでもなく記事の見出しがセメレーニ・オスヴァルドに変更されたことはしかるべきことで、非常に重要だと思うのですが、一方でこの記事の編集者が転送処理を忘れたり削除してしまうことにより、「オズワルド・セメレーニ」で覚えていた人の中には、彼の名前は実際にはセメレーニ・オスヴァルドと表記されるべきで、オズワルド・セメレーニで覚えた人はGoogleの検索結果に彼の名前がないことから、永遠にその事実を知ることはおろか、彼の記事がきちんと存在することを知る機会を逸してしまう可能性があるということが起こり得てしまいます。
これらの解消に向けて
私としては、
- 見出し語をきちんと併記しておけばURLが見出し語のリンクでなくても、どこに飛ぶのか可視的である
- 見出し語が全角文字の場合、全角部分など非ASCIIというか非ANSIの文字部分がURLだと認識されず、例えば“https://ary.wikipedia.org/wiki/لفارسية”という記事に飛んで欲しいのに半角部分の“https://ja.wikipedia.org/wiki/”に飛んでしまったりということが予防できる
- そもそも〈2〉のような文字をサポートしていないWebページやアプリケーションソフトへのリンクの貼り付けが容易になる
- 〈2〉と〈3〉の回避策としてパーセントエンコーディングがあるが、どちらにせよパーセントエンコーディングの場合は可読性に問題が発生してしまい、かつURLの文字数が過度に冗長になってしまうため、それを防ぐことができる
といったメリットの多さから、極力、“wikipedia.org/?curid=記事ID”の表記を用いるようにするのが望ましいと考えられます。
すなわち、“لفارسية”のような記事を案内する場合に、
Wikipediaタイトル:لفارسية
Page(s)ID:6103
タイトル込みURL:https://ary.wikipedia.org/wiki/لفارسية
PC用エンコード済みURL:https://ary.wikipedia.org/wiki/%D9%84%D9%81%D8%A7%D8%B1%D8%B3%D9%8A%D8%A9
Mobile用エンコード済みURL:https://ary.m.wikipedia.org/?curid=%D9%84%D9%81%D8%A7%D8%B1%D8%B3%D9%8A%D8%A9
PC用ID込みURL:https://ary.wikipedia.org/?curid=6103
Mobile用ID込みURL:https://ary.m.wikipedia.org/?curid=6103
出力されるようにすれば、その中で例えば
Wikipediaタイトル:لفارسية
PC用ID込みURL:https://ary.wikipedia.org/?curid=6103
Mobile用ID込みURL:https://ary.m.wikipedia.org/?curid=6103
の部分だけSNSやメッセンジャーにコピペすれば、意図しないエラーを防ぐことができ、可読性を高めることができるということです。
必要なモジュール
pipで必要なモジュールは以下の通りです。なお、Python 3.12からrequestモジュールなど一部のモジュールがpipでインストールできないために、方法については「初中級者向け:MacOS用IDE“CodeRunner 4”でPython仮想環境内でコードを実行する方法」をご参照ください。
pip install urllib.parse
pip install requests
pip install pyperclip
ソースコード
このコードはPython 3とPythonista 3に対応しています。
import sys
import urllib.parse
import requests
import re
try:
import clipboard
def get_clipboard():
return clipboard.get()
def set_clipboard(text):
clipboard.set(text)
except ImportError:
try:
import pyperclip
def get_clipboard():
return pyperclip.paste()
def set_clipboard(text):
pyperclip.copy(text)
except ImportError:
sys.exit("クリップボードモジュールが利用できません。")
class ClipboardURLFetcher:
def fetch_url(self):
url = get_clipboard()
if not url:
sys.exit("クリップボードに何も入っていません。")
return urllib.parse.unquote(url)
class ClipboardManager:
@staticmethod
def copy_to_clipboard(text):
set_clipboard(text)
class WikiURLProcessor:
def __init__(self, site):
self.site = site
def process_url(self, url):
if '?curid=' in url:
sys.exit(f'既に変換済みです:{url}')
if 'https://' not in url or (f'.{self.site}.org/wiki/' not in url and f'.m.{self.site}.org/wiki/' not in url):
return None
if f'.m.{self.site}.org/wiki/' in url:
url = url.replace(f'.m.{self.site}.org/wiki/', f'.{self.site}.org/wiki/')
match = re.search(r'https://([a-z\-]+)\.' + re.escape(self.site) + r'\.org/wiki/', url)
if not match:
sys.exit(f'無効なURLです:{url}')
lang = match.group(1)
text = url.replace(f'https://{lang}.{self.site}.org/wiki/', '')
page_id = self.get_page_id(lang, text)
if not page_id:
sys.exit(f'変換不可能なリンクです:{url}')
new_url = f'https://{lang}.{self.site}.org/?curid={page_id}' if self.site == 'wikipedia' else f'https://{lang}.{self.site}.org/w/index.php?curid={page_id}'
ClipboardManager.copy_to_clipboard(new_url)
self.print_info(url, lang, text, page_id)
return new_url
def get_page_id(self, lang, title):
url = f'https://{lang}.{self.site}.org/w/api.php'
params = {
'action': 'query',
'titles': title,
'format': 'json'
}
response = requests.get(url, params=params)
data = response.json()
page = next(iter(data['query']['pages'].values()))
return page.get('pageid')
def print_info(self, url, lang, text, page_id):
encoded_url = urllib.parse.quote(url, safe='/:=@,.!?\"\'')
mobile_url = url.replace(f'.{self.site}.org/wiki/', f'.m.{self.site}.org/?curid=')
mobile_encoded_url = urllib.parse.quote(mobile_url, safe='/:=@,.!?\"\'')
print(f'{self.site.capitalize()}タイトル:{text}')
print(f'Page(s)ID:{page_id}')
print(f'タイトル込みURL:{url}')
print(f'PC用エンコード済みURL:{encoded_url}')
print(f'Mobile用エンコード済みURL:{mobile_encoded_url}')
print('')
print(f'{self.site.capitalize()}タイトル:{text}')
print(f'PC用ID込みURL:https://{lang}.{self.site}.org/?curid={page_id}')
print(f'Mobile用ID込みURL:https://{lang}.m.{self.site}.org/?curid={page_id}')
def main():
fetcher = ClipboardURLFetcher()
url = fetcher.fetch_url()
if 'wikipedia.org/wiki/' in url:
WikiURLProcessor('wikipedia').process_url(url)
elif 'wiktionary.org/wiki/' in url:
WikiURLProcessor('wiktionary').process_url(url)
if __name__ == "__main__":
main()
以上です。
おわりに
今までの記事ではWikipediaとWiktionaryとで別処理をしていましたが、今回のコードで重複しないように工程を変えてみました。