2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Pythonでクリップボードをリンク付き(HTML形式)加工する。

Posted at

はじめに

 クリップボード操作をするPythonライブラリはpyperclipが有名だが、このライブラリは文字ベースでしか扱えず、リンク付きのHTML形式で扱うことができない。この記事ではwin32clipboardを使ってHTML形式のクリップボードを扱う方法をまとめる。シチュエーションはSharepoint等のURLコピーしたクリップボードデータを、リンク付きのHTMLデータとして加工することを想定する。Windows限定であることは注意。

目次

クリップボードのHTML形式ってどういうフォーマット?

 URLコピーしたデータを、Excel、PowerPointやTeams等に貼り付けると文字リンク付きのデータになる。この文字リンク付きのクリップボードデータがどういうものか?は、クリップ見え窓を使うと確認できる。

image.png

 https://qiita.com/timelineをHTML形式にすると下記のようになっている。本体は<a href= ~ </a>の部分で、<!--StartFragment--><!--EndFragment-->で囲まれている。先頭の4行の10桁の数字は、それぞれのオフセット位置を10進数で表記したものである。このフォーマットの詳細はMicrosoftのサイトにまとまっている。
https://learn.microsoft.com/ja-jp/windows/win32/dataxchg/html-clipboard-format

クリップボードHTML形式
Version:0.9
StartHTML:0000000105
EndHTML:0000000244
StartFragment:0000000141
EndFragment:0000000208
<html>
<body>
<!--StartFragment--><a href="https://qiita.com/timeline">タイムライン - Qiita</a><!--EndFragment-->
</body>
</html>

戻る

win32clipboardを使う。

 では、本題のwin32clipboardについて。pip install pywin32でモジュールをインストール。名称が違うので注意。

クリップボード取得

win32clipboard.GetClipboardData()でクリップボード取得する。前後にOpen/Closeの処理が必要。この操作で、テキストベースのクリップデータを取得できる。

クリップボード取得
import win32clipboard

win32clipboard.OpenClipboard()
clipdata = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()

#クリップデータ確認
print(clipdata)

クリップボード設定

win32clipboard.SetClipboardData()で設定する。クリップボード取得と同じく前後にOpen/Closeの処理が必要。また設定前の情報をクリアするためEmptyも実施する。Emptyは必須でないが、実施しておいた方が無難。パラーメータを設定することで、クリップボードに設定するフォーマットを選択できる。win32clipboard.CF_UNICODETEXTとすることで日本語のマルチバイトをTEXT形式で設定ができる。

クリップボード設定(TEXT形式)
import win32clipboard

#clipdataにクリップボードに設定したい文字列を入れる。
clipdata = 'テスト'
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()	
win32clipboard.SetClipboardData(win32clipboard.CF_UNICODETEXT, clipdata.encode('UTF-8'))
win32clipboard.CloseClipboard()

HTML形式でクリップボードに設定する場合はCF_HTMLというパラメータがないので、代わりに
win32clipboard.RegisterClipboardFormat('HTML Format')を設定する。設定するHTMLデータは クリップボードのHTML形式ってどういうフォーマット?のフォーマットで記述が必要。「 https://qiita.com/ 」のリンク文字を 「Qiitaのリンク」という文字にする例は下記の通り。clipboard_to_html_format()は各種ヘッダやオフセットの計算をする自作関数。

クリップボード設定(HTML形式)
import win32clipboard

#------------------------------
# HTML形式に変換する
#------------------------------
def clipboard_to_html_format(in_html_data):
	#HTML形式用の前後データ
	header     = 'Version:0.9\nStartHTML:0000000000\nEndHTML:0000000000\nStartFragment:0000000000\nEndFragment:0000000000\n'
	html_start = '<html><body><!--StartFragment-->'
	html_end   = '<!--EndFragment--></body></html>'
	
	#オフセット計算
	offset_s_html = '{:010d}'.format(len(header))											# StartHTML
	offset_e_html = '{:010d}'.format(len(header + html_start + in_html_data + html_end))	# EndHTML
	offset_s_frag = '{:010d}'.format(len(header + html_start))								# StartFragment
	offset_e_frag = '{:010d}'.format(len(header + html_start + in_html_data))				# EndFragment

	#オフセットデータ書き換え
	header = 'Version:0.9\nStartHTML:'+offset_s_html+'\nEndHTML:'+offset_e_html+'\nStartFragment:'+offset_s_frag+'\nEndFragment:'+offset_e_frag+'\n'
	
	#結合
	return header + html_start + in_html_data + html_end


#------------------------------
# main
#------------------------------
#「https://qiita.com/」のリンク文字を「Qiitaのリンク」とする
clipdata = '<a href="https://qiita.com/">Qiitaのリンク</a>'

#html形式に変更
clipdata = clipboard_to_html_format(clipdata)

# html形式で設定
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()	
win32clipboard.SetClipboardData(win32clipboard.RegisterClipboardFormat('HTML Format'), clipdata.encode('UTF-8'))
win32clipboard.CloseClipboard()

TEXT形式とHTML形式両方設定したい場合はwin32clipboard.SetClipboardData()を2行並列して記述すればよい。
戻る

コピーしたURLリンクを加工する例。

コピーしたURLを下記のように 「リンク」と「URL」併記したクリップボードに加工する例。
image.png

👆のPythonコードはこちら。
clipboard_html.py
import win32clipboard	#クリップボード処理 pip install pywin32
import urllib.parse		#URLのデコード処理

#------------------------------
#URLの日本語デコード
#------------------------------
def url_decode(in_url):
	return urllib.parse.unquote(in_url)

#------------------------------
# HTML形式に変換する
#------------------------------
def clipboard_to_html_format(in_html_data):
	#HTML形式用の前後データ
	header     = 'Version:0.9\nStartHTML:0000000000\nEndHTML:0000000000\nStartFragment:0000000000\nEndFragment:0000000000\n'
	html_start = '<html><body><!--StartFragment-->'
	html_end   = '<!--EndFragment--></body></html>'
	
	#オフセット計算
	offset_s_html = '{:010d}'.format(len(header))											# StartHTML
	offset_e_html = '{:010d}'.format(len(header + html_start + in_html_data + html_end))	# EndHTML
	offset_s_frag = '{:010d}'.format(len(header + html_start))								# StartFragment
	offset_e_frag = '{:010d}'.format(len(header + html_start + in_html_data))				# EndFragment

	#オフセットデータ書き換え
	header = 'Version:0.9\nStartHTML:'+offset_s_html+'\nEndHTML:'+offset_e_html+'\nStartFragment:'+offset_s_frag+'\nEndFragment:'+offset_e_frag+'\n'
	
	#結合
	return header + html_start + in_html_data + html_end

#------------------------------
# クリップボードに設定
# cliptype     :'HTML'(HTML形式とTEXT形式)/'TEXT'(TEXT形式のみ)
# clipdata_text:TEXT形式データ
# clipdata_html:HTML形式データ
#------------------------------
def clipboard_set(clipdata_text, clipdata_html='', cliptype='TEXT'):
	win32clipboard.OpenClipboard()
	win32clipboard.EmptyClipboard()
	
	if cliptype == 'HTML':
		win32clipboard.SetClipboardData(win32clipboard.RegisterClipboardFormat('HTML Format'), clipdata_html.encode('UTF-8'))
		win32clipboard.SetClipboardData(win32clipboard.CF_UNICODETEXT, clipdata_text.encode('UTF-8'))
	elif cliptype == 'TEXT':
		win32clipboard.SetClipboardData(win32clipboard.CF_UNICODETEXT, clipdata_text.encode('UTF-8'))
	else:
		print('The format is not defined.')
	
	win32clipboard.CloseClipboard()

#------------------------------
# クリップボードから取得
# cliptype     :'HTML'(HTML形式)/'TEXT'(TEXT形式のみ)
#------------------------------
def clipboard_get(cliptype='TEXT'):
	win32clipboard.OpenClipboard()
	
	if cliptype == 'HTML':
		clipdata = win32clipboard.GetClipboardData(win32clipboard.RegisterClipboardFormat('HTML Format'))
	elif cliptype == 'TEXT':
		clipdata = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT)
	else:
		clipdata = 'The format is not defined.'

	win32clipboard.CloseClipboard()
	
	return clipdata


#------------------------------
# main
#------------------------------

#クリップボードから取得し日本語デコード
url_data = url_decode(clipboard_get())

#下記のようになるようHTML記述
#---------------
#リンク
#http://xxxxxxxx
#---------------
htmldata = '<a href="'+url_data+'">リンク<br>'+url_data+'</a><br>'

#クリップボード設定
clipboard_set(url_data, clipboard_to_html_format(htmldata), 'HTML')

戻る

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?