py-py’s blog

何か書くよ

urlopen()で引数に日本語が含まれているとアクセスできない件【追記あり】

今までファイルを取得してきた中でファイル名に日本語が含まれているものが少なかった。

今回日本語が含まれるファイルがいくつかあったため、その際に取った方法を。

サンプルurl: http://www.nantara.com/ほげほげ.jpg

流れ

①urlに日本語があるか確認する
②日本語があった場合urlopen()でも読める文字列へ変換する

from urllib.parse import quote_plus
import unicodedata
from urllib.request imprort urlopen


def is_japanese_include(url: str) -> bool:
    """
    引数の文字列に日本語があるか確認する
    一字でもあった場合、Trueが返る
    """
    for chara in string:
        name = unicodedata.name(chara)
        if "CJK UNIFIED" in name or "HIRAGANA" in name or "KATAKANA" in name:
            return True
        return False

def edit_string(url: str) -> string:
    """
    urlopen()が読めるように編集する
    """
    tmp_idx = url.rfind("/")
    url_part = url[:tmp_idx]
    japanese_part = url[tmp_idx + 1:]
    url = url_part + "/" + quote_plus(japanese_part, encoding="utf-8")
    return url

def main():
    url: str = "http://www.nantara.com/ほげほげ.jpg"
    is_japanese_include_result: bool = is_japanese_include(url)
    if is_japanese_include_result:
        edited_url = edit_string(url)
        urlopen(edited_url)

if __name__  "__main__":
    main()

ポイントは、日本語の部分を「quote_plus(japanese_part, encoding="utf-8")」で加工しているところ。

参考

minus9d.hatenablog.com

qiita.com

【20190621追記】

上記のプログラムを使っても取得できないファイルが出てきた。

サンプルurl: http://www.nantara.com/ほげほげ .jpg

違いは、ファイル名に空白が含まれるか否か。

pythonのurllib.parseのquote_plus()は、url内の空白を「+」へ置き換える。 (だからquote_plusなのか、、)

docs.python.org

そして空白を「+」に置き換えられたurlは正しくなく、urlopen()でアクセスはできなかった。

ではこの「+」を何に置き換えれば良いかと思い以下の記事を参考にした。

www.suzukikenichi.com

上記記事内の引用から

TL;DR: use “+” or “%20” in the query-string, use “%20” within the rest of the URL.

空白表すなら「%20」でOK、と解釈したぞ、私は。

つまり、quote_plus()で「+」が発生したら、それを「%20」に置き換える、ということで良いようだ。

以上から、プログラムを修正する。

from urllib.parse import quote_plus
import unicodedata
from urllib.request import urlopen


def is_japanese_include(url: str) -> bool:
    """
    引数の文字列に日本語があるか確認する
    一字でもあった場合、Trueが返る
    """
    for chara in string:
        name = unicodedata.name(chara)
        if "CJK UNIFIED" in name or "HIRAGANA" in name or "KATAKANA" in name:
            return True
        return False

def edit_string(url: str) -> string:
    """
    urlopen()が読めるように編集する
    """
    tmp_idx = url.rfind("/")
    url_part = url[:tmp_idx]
    japanese_part = url[tmp_idx + 1:]
    url = url_part + "/" + quote_plus(japanese_part, encoding="utf-8")
    if "+" in url:
        url = url.replace("+", "%20")
    return url

def main():
    url: str = "http://www.nantara.com/ほげほげ .jpg"
    edited_url: str = ""
    is_japanese_include_result: bool = is_japanese_include(url)
    if is_japanese_include_result:
        edited_url = edit_string(url)
    if edited_url == "":
        urlopen(url)
    else:
        urlopen(edited_url)

if __name__  "__main__":
    main()