Python3でとあるURLに日本語パラメータでアクセスするときの文字コードについて

HTTPの主たるメソッドであるGET/POSTについて。Pythonで書いたコードからサイボウズの設定を更新したいので、POSTを対象にして実験してます。普段UTF-8しか使わない僕は想定通りShift_JISで書かれたサイボウズに泣かされるのであります。
python2系から3系になったことで、Unicodeや文字列に対する考え方が変わっていて、今までInの時とOutの時に「外に合わせれば動く」という考えだけでよかったのがうまくいかなくなった。たとえば"スパム!".encode("utf-8")がbytes型になる、とかにより。

ログインからさきのセッション管理はhttp.cookiejarを使えば簡単なのでそれはよしとして、POSTするときのクエリの文字コードがメインテーマとなります。

検索クエリをURLエンコードする際、日本語の文字列を正しくエンコードしするためにurllib.parse.quote_plus()を使う。ここではそれをprintで表示する*1

import urllib.request
import urllib.parse

opener = urllib.request.build_opener()
r = opener.open("http://search.yahoo.co.jp/search?ei=shift_jis&p=" \
    + urllib.parse.quote_plus("天使ちゃんマジ天使",encoding="sjis"))
print(r.readall().decode("utf-8"))

日本語が出てこないなら(UALエンコード不要な文字なら)、"?"と"&"でjoinするようなカッコ悪い実装をしなくても、

params = urllib.parse.urlencode({"ei" : "Shift_JIS" ,
                                 "p" : "tenshi maji"})
r = opener.open("http://search.yahoo.co.jp/search", data=params)
print(r.readall().decode("utf-8"))

ってな具合にすればいける。
POSTについてもyahooでは2010/07/29時点では試すことができて、下記の通り。

r = opener.open("http://search.yahoo.co.jp/search" ,
                data = "ei=Shift_JIS&p=" \
                + urllib.parse.quote_plus("天使ちゃんマジ天使",encoding="sjis"))
print(r.readall().decode("utf-8"))

urllib.parse.urlencode()で辞書使ってかつ日本語解釈ってできないのかしら。
動くようになったし、まぁいっか。

*1:自前環境がUTF-8だからprint()するときはUTF-8にデコードしている。