66218


# 問題

言語処理100本ノックの「３章正規表現 29. 国旗画像のURLを取得する」の問題について、回答でどの部分を修正したらいいかわからないです。

[Qiita記事「言語処理100本ノックに挑戦 / 第3章:
正規表現」](https://qiita.com/saitotak/items/93199f01b57fea95113f)に掲載されていた回答では、「国章のURL」を取得するプログラムになっていたので、国旗のURLに変更しようとしています。

# エラー

回答コードの以下の箇所を変更して、プログラムを実行しましたが、

[code]

    image_name = re.sub('\[\[ファイル:(.*?)\|.*\]\]','\\1',match_dct['国章画像']) # ファイル名を抽出
    
    'titles': 'File:Royal%20Coat%20of%20Arms%20of%20the%20United%20Kingdom.svg',
    
[/code]

エラーが出てしまい、他にどこを修正する必要があるのか分かりません。

[code]

    $ python 29.py
    Traceback (most recent call last):
      File "29.py", line 36, in <module>
        print(data.get('query').get('pages').get('-1').get('imageinfo')[0].get('url'))
    AttributeError: 'NoneType' object has no attribute 'get'
    
[/code]

# 実行プログラム

国旗画像のURLは「<https://ja.wikipedia.org/wiki/%E3%82%A4%E3%82%AE%E3%83%AA%E3%82%B9%E3%81%AE%E5%9B%BD%E6%97%97#/media/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Flag_of_the_United_Kingdom.svg>」だったので、以下のように修正しました。

[code]

    import gzip, json, re
    import urllib.request
    
    
    file = 'jawiki-country.json.gz'
    
    
    def extract_info():
        with gzip.open(file, 'rt') as openfile:
            for line in openfile:
                jsondata = json.loads(line)
                if jsondata['title'] == 'イギリス' :
                    return jsondata['text']
        #if there is no data follwoing the title
        raise ValueError('There is no data with the given title.')
    
    match = re.findall('^\{\{基礎情報(.*?)\}\}$',extract_info(),re.MULTILINE+re.DOTALL)
    match2 = re.findall('\|(.*?) = (.*?)\n',match[0])
    match_dct = dict(match2)
    
    
    image_name = re.sub('\[\[ファイル:(.*?)\|.*\]\]','\\1',match_dct['国旗画像']) # ファイル名を抽出
    param = {
        'format': 'json',
        'action': 'query',
        'titles': 'File:Flag%20of%20the%20United%20Kingdom.svg',
        'prop': 'imageinfo',
        'iiprop': 'url'
    }
    
    query = '&'.join("%s=%s" % (k, v) for k, v in param.items())
    url = 'http://en.wikipedia.org/w/api.php?%s'  % (query)
    request = urllib.request.urlopen(url)
    jsonData = request.read().decode('utf-8')
    data = json.loads(jsonData)
    print(data.get('query').get('pages').get('-1').get('imageinfo')[0].get('url'))
    
[/code]

# 試したこと

同問題の別回答「[素人の言語処理100本ノック:29](https://qiita.com/segavvy/items/fc7257012d8a590185e5)」より、`titles=File:'
+
urllib.parse.quote(fname_flag)`の表記を用いて試してみましたが、こちらも同じエラーが出て、別に問題がある可能性も考えられますが、１人では特定できない状態です。

[code]

    import gzip, json, re
    import urllib.request
    
    
    file = 'jawiki-country.json.gz'
    
    
    def extract_info():
        with gzip.open(file, 'rt') as openfile:
            for line in openfile:
                jsondata = json.loads(line)
                if jsondata['title'] == 'イギリス' :
                    return jsondata['text']
        #if there is no data follwoing the title
        raise ValueError('There is no data with the given title.')
    
    match = re.findall('^\{\{基礎情報(.*?)\}\}$',extract_info(),re.MULTILINE+re.DOTALL)
    match2 = re.findall('\|(.*?) = (.*?)\n',match[0])
    match_dct = dict(match2)
    
    
    image_name = re.sub('\[\[ファイル:(.*?)\|.*\]\]','\\1',match_dct['国旗画像']) # ファイル名を抽出
    param = {
        'format': 'json',
        'action': 'query',
        'titles': 'File:' + urllib.parse.quote(image_name),
        'prop': 'imageinfo',
        'iiprop': 'url'
    }
    
    query = '&'.join("%s=%s" % (k, v) for k, v in param.items())
    url = 'http://en.wikipedia.org/w/api.php?%s'  % (query)
    request = urllib.request.urlopen(url)
    jsonData = request.read().decode('utf-8')
    data = json.loads(jsonData)
    print(data.get('query').get('pages').get('-1').get('imageinfo')[0].get('url'))
    
[/code]

出力

[code]

    $ python 29.py
    Traceback (most recent call last):
      File "29.py", line 36, in <module>
        print(data.get('query').get('pages').get('-1').get('imageinfo')[0].get('url'))
    AttributeError: 'NoneType' object has no attribute 'get
    
[/code]


CC BY-SA 4.0
2020-05-02T05:42:43.603
66198
2020-05-02T15:58:07.847
question
python json 正規表現 web-scraping
JSONデータから指定した値を取得するときのエラー


何の意味があるのかは分かりませんが、途中に指定している`.get('-1')`の時点で`None`が返ってくるため、その後の`.get('imageinfo')`でエラーになっているようです。

`data.get('query')`だけした結果を見ると以下のようになっているので、ここで別の値を指定する必要があるでしょう。

国章の場合：

[code]

    {'pages': {'-1': {'ns': 6, 'title': 'File:Royal Coat of Arms of the United Kingdom.svg', 'missing': '', 'known': '', 'imagerepository': 'shared', 'imageinfo': [{'url': 'https://upload.wikimedia.org/wikipedia/commons/9/98/Royal_Coat_of_Arms_of_the_United_Kingdom.svg', 'descriptionurl': 'https://commons.wikimedia.org/wiki/File:Royal_Coat_of_Arms_of_the_United_Kingdom.svg', 'descriptionshorturl': 'https://commons.wikimedia.org/w/index.php?curid=21101265'}]}}}
    
[/code]

国旗の場合：

[code]

    {'pages': {'23473560': {'pageid': 23473560, 'ns': 6, 'title': 'File:Flag of the United Kingdom.svg', 'imagerepository': 'local', 'imageinfo': [{'url': 'https://upload.wikimedia.org/wikipedia/en/a/ae/Flag_of_the_United_Kingdom.svg', 'descriptionurl': 'https://en.wikipedia.org/wiki/File:Flag_of_the_United_Kingdom.svg', 'descriptionshorturl': 'https://en.wikipedia.org/w/index.php?curid=23473560'}]}}}
    
[/code]

なので、`.get('-1')`を`.get('23473560')`に変えると上手く取得できました。

[code]

    print(data.get('query').get('pages').get('23473560').get('imageinfo')[0].get('url'))
    
[/code]

とすると結果は以下になります。

[code]

    https://upload.wikimedia.org/wikipedia/en/a/ae/Flag_of_the_United_Kingdom.svg
    
[/code]


CC BY-SA 4.0
2020-05-02T15:58:07.847
66218
2020-05-02T15:58:07.847
26370
66198
answer