質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

1054閲覧

Python re.findallの挙動がおかしい

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2020/07/27 08:03

re.findallの挙動がおかしいと書きましたが,具体的にはマッチしている文字列が一文字しかヒットしない現象が起きて困っています.

ソースコード

以下のコードは天気予報サイトから時刻,降水量,気温のデータを抜き出すことを目的としています.

Python

1import os 2import re 3import requests 4import urllib.request 5 6Weather_URL = 'https://weathernews.jp/onebox/35.7425784/139.7013585/' 7 8with urllib.request.urlopen(Weather_URL) as response: 9 html = response.read().decode() 10 seiki = r'<div class="weather-day__head">(.|\s)*?<div class="weather-day">' 11 reseiki = re.search(seiki, html).group() 12 print(reseiki) 13 14 time = re.findall(r'<p class="weather-day__time">(.|\s)*?</p>',reseiki) 15 rain = re.findall(r'<p class="weather-day__r">(.|\s)*?</p>',reseiki) 16 temp = re.findall(r'<p class="weather-day__t">(.|\s)*?</p>',reseiki) 17 18 print(time) 19 print(rain) 20 print(temp)

結果

print(reseiki)

print(reseiki)

1<p>Hour</p><p>Weather</p><p>Precip.</p><p>Temp.</p><p>Wind</p> 2 </div> 3 <div class="weather-day__body"> 4 <div class="weather-day__item"> 5 <p class="weather-day__time">17:00</p> 6 <p class="weather-day__icon"><img src="//smtgvs.cdn.weathernews.jp/onebox/img/wxicon/300.png"></p> 7 <p class="weather-day__r">1mm/h</p> 8 <p class="weather-day__t">81°F</p> 9 <p class="weather-day__w">3m/s<br>SSW</p> 10 </div> 11 <div class="weather-day__item"> 12 <p class="weather-day__time">18:00</p> 13 <p class="weather-day__icon"><img src="//smtgvs.cdn.weathernews.jp/onebox/img/wxicon/300.png"></p> 14 <p class="weather-day__r">1mm/h</p> 15 <p class="weather-day__t">81°F</p> 16 <p class="weather-day__w">3m/s<br>SSW</p> 17 </div> 18 <div class="weather-day__item"> 19 <p class="weather-day__time">19:00</p> 20 <p class="weather-day__icon"><img src="//smtgvs.cdn.weathernews.jp/onebox/img/wxicon/300.png"></p> 21 <p class="weather-day__r">1mm/h</p> 22 <p class="weather-day__t">81°F</p> 23 <p class="weather-day__w">3m/s<br>SSW</p> 24 </div> 25 <div class="weather-day__item"> 26 <p class="weather-day__time">20:00</p> 27 <p class="weather-day__icon"><img src="//smtgvs.cdn.weathernews.jp/onebox/img/wxicon/200.png"></p> 28 <p class="weather-day__r">0mm/h</p> 29 <p class="weather-day__t">81°F</p> 30 <p class="weather-day__w">2m/s<br>SSW</p> 31 </div> 32 <div class="weather-day__item"> 33 <p class="weather-day__time">21:00</p> 34 <p class="weather-day__icon"><img src="//smtgvs.cdn.weathernews.jp/onebox/img/wxicon/200.png"></p> 35 <p class="weather-day__r">0mm/h</p> 36 <p class="weather-day__t">79°F</p> 37 <p class="weather-day__w">2m/s<br>SSW</p> 38 </div> 39 <div class="weather-day__item"> 40 <p class="weather-day__time">22:00</p> 41 <p class="weather-day__icon"><img src="//smtgvs.cdn.weathernews.jp/onebox/img/wxicon/200.png"></p> 42 <p class="weather-day__r">0mm/h</p> 43 <p class="weather-day__t">79°F</p> 44 <p class="weather-day__w">2m/s<br>SSW</p> 45 </div> 46 <div class="weather-day__item"> 47 <p class="weather-day__time">23:00</p> 48 <p class="weather-day__icon"><img src="//smtgvs.cdn.weathernews.jp/onebox/img/wxicon/200.png"></p> 49 <p class="weather-day__r">0mm/h</p> 50 <p class="weather-day__t">79°F</p> 51 <p class="weather-day__w">2m/s<br>SSW</p> 52 </div> 53 </div> 54 </div> 55 <div class="weather-day"> 56

print(time)
print(rain)
print(temp)

print()

1['0', '0', '0', '0', '0', '0', '0'] 2['h', 'h', 'h', 'h', 'h', 'h', 'h'] 3['F', 'F', 'F', 'F', 'F', 'F', 'F']

と,print(reseiki)では正しく抽出範囲を絞れているのに,そこから正規表現で時刻,降水量,気温のデータが上手く抜き出せていない,というよりかは何故か最後の一文字しか抜き出せておりません.

試したこと

・time,rain,tempの方をtype()で調べてみたが普通にリスト型
・findallの返り値について調べなおしたが普通にlists(その中身もstr)が返り値だしおかしい...

誰かご教授願えないでしょうか?よろしくお願いします.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

キャプチャ用の()と、その中でキャプチャしない(?:)を使って、

Python

1 time = re.findall(r'<p class="weather-day__time">((?:.|\s)*?)</p>', reseiki) 2 rain = re.findall(r'<p class="weather-day__r">((?:.|\s)*?)</p>', reseiki) 3 temp = re.findall(r'<p class="weather-day__t">((?:.|\s)*?)</p>', reseiki)

で得られる結果(の後半)は、

['18:00', '19:00', '20:00', '21:00', '22:00', '23:00'] ['0.5mm/h', '0.5mm/h', '0.5mm/h', '0mm/h', '0mm/h', '0mm/h'] ['81°F', '81°F', '79°F', '79°F', '79°F', '79°F']

投稿2020/07/27 08:38

Daregada

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/07/27 08:42

まさしく求めていた結果になります,ですが私は >その中でキャプチャしない(?:)を使って、 の下りがいまいち理解できません,何故これを使わないといけないのでしょうか? 変な質問でしたたらすみません.
Daregada

2020/07/27 08:52 編集

ええと、正規表現の ( ) は、いくつかの役割を課されていて、グループ化とかキャプチャとか(今回は関係ないが、後読み・先読みの一部とか)として使われます。キャプチャ(部分文字列の保存)をしてしまうと、findallはそれを返り値に含めてしまうので、 [('0.5mm/h', 'h'), ('0.5mm/h', 'h'), ……] みたいな返り値になってしまいます。そこで、キャプチャを行なわずグループ化だけを行なう (?: ) を、内側のパターンに指定しています。
退会済みユーザー

退会済みユーザー

2020/07/27 09:13

この文章の意味が半分くらいしか理解できず,正規表現の知識が全く足りないことがわかりました.まずグループ化キャプチャ等の理解を目指してこれから勉強しようと思います.本質問の求めている解答も得られ,理解しなくてはならないこともわかりました.ありがとうございます.
guest

0

findallの理解不足です。
(.|\s)と1文字だけキャプチャーしているので、それだけが抽出されます。

キャプチャーするのが意図通りじゃないのなら、(?:.|\s)とキャプチャーしないグループにします。

あるいは、これはおそらく「改行も含んだ任意の1文字」を表したいのだと思いますが、それは普通は[\s\S]と書きます。

投稿2020/07/27 08:23

otn

総合スコア84798

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

https://docs.python.org/ja/3/library/re.html#re.findall

パターン中に1つ以上のグループがあれば、グループのリストを返します。

(.|\s) このグループにヒットした1文字がリストになっているのでfindallの仕様通りです。


そもそも(.|\s)の意図はなんでしょう?
任意の一文字または空白文字 は 任意の一文字 となにか違いますか?

pyhton

1 time = re.findall(r'<p class="weather-day__time">(.*?)</p>', reseiki, re.DOTALL) 2 rain = re.findall(r'<p class="weather-day__r">(.*?)</p>', reseiki, re.DOTALL) 3 temp = re.findall(r'<p class="weather-day__t">(.*?)</p>', reseiki, re.DOTALL)

としたかったのではないでしょうか?

投稿2020/07/27 09:04

編集2020/07/27 09:09
quickquip

総合スコア11061

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問