プロが教える店舗&オフィスのセキュリティ対策術

プログラミング初心者です。
ユーチューブを見ながらウェブスクレイピングに初めて挑戦しているのですが、中々うまく行きません。
やりたいこととしては、Google Colaboratoryを使用し、下記のサイトから各病院名と住所をテキストとして抽出(〇〇病院、〇〇県、〇〇市、、、、のように)しGoogleドライブに保存することです。下記サイトは4ページありますが、全てのページでスクレイピングを行えるようにしたいと考えております。

↓スプレイピングしたいサイトURL
https://petlife.asia/hospital/search/aomori/


もし可能であれば、下記リンクのような形でコードを教えていただくことはできないでしょうか。

https://colab.research.google.com/drive/1P1yGfCE … 

大変で面倒くさい作業と思いますが、もし少しでもお力いただける方がいましたらよろしくお願いします。私も今必死に勉強しています。

A 回答 (6件)

ん〜。

こういう事がやりたいのかな。
(もちろん、ローカルじゃこのコードは動かないんで、あくまでGoogle Colaboratory上で)

## ここから

from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials

auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)

shop_names, addresses = [], []

for i in range(1, 5):
 page_url = "https://petlife.asia/hospital/search/aomori/?pag … + str(i)
 r = requests.get(page_url)

 soup = BeautifulSoup(r.text, features="html.parser")

 h2_tags = soup.find_all("h2", class_="shop_name")
 shop_names += [tags.a.text for tags in h2_tags]

 td_tags = soup.find_all("td", class_="address")
 addresses += [tags.get_text().split()[0] for tags in td_tags]

with open("animal_clinic.csv", "w") as f:
 [csv.writer(f).writerow(d) for d in zip(shop_names, addresses)]

upload_file_2 = drive.CreateFile()
upload_file_2.SetContentFile("animal_clinic.csv")
upload_file_2.Upload()

## ここまで

基本的には貴方が参照したページ( https://colab.research.google.com/drive/1P1yGfCE … )の通りなんで特に説明する事は無いんですが・・・。

ただ、結論から言うと、「プログラミングが上手く行かない」んじゃなくって、多分HTMLを読む事が出来なかったのでは、と思います。
要するに、該当のページ( https://petlife.asia/hospital/search/aomori/ )のHTMLソースを読んでなかったんじゃないか・・・つまり、参照ページだとタイトルをスクレイピングする際にh1タグを抽出してますが、それをそのままやると上手く行かないのは当然です。貴方のスクレイピングしたいページでは、例えば病院名はh2タグです。
それを知る為にはHTMLのソースを読まなきゃならなくって、そこは「人力」で判断するしかないんです(笑)。該当ページを出して、右クリックすれば恐らく【ページのソースを表示】かそれに類するコマンドがあって、それを選べばHTMLのソースが見れる。そこから一体何が「病院名」のタグなのか、そして「住所」が表示されるタグなのか・・・そういう「下調べ」しないとこーゆーのは何とも上手くいかないんですよ。
だから「上手く行かなかった」のはプログラミングの技術的な問題と全く関係ない事柄に躓いてたんじゃないのかしら。

まあ、何か他に質問があったら受け付けるつもりではいますが、多分問題はそんなトコでしょう。
    • good
    • 0
この回答へのお礼

丁寧にご教示いただき誠にあがとうございます、大変助かりました。
自分ではできなかったのはHTMLへの理解やその他全般的な知識が抜けていることが原因です。
一点質問をさせていただきたいのですが、for i in range(1,5):の段から実行しますと、下記のエラーが出てきます。

「 File "<ipython-input-6-df312b238a6b>", line 3
page_url = "https://petlife.asia/hospital/search/aomori/?pag … + str(i)
^
SyntaxError: invalid character in identifier」


これは page_url = "https://petlife.asia/hospital/search/aomori/?pag … + str(i) の中に使用できない文字があるということですが、何が問題なのでしょうか。よろしくお願いします。

お礼日時:2020/07/26 16:30

> 1ページ目の住所が抽出できない症状が出てしまっているようです。



それはおかしいですねぇ。
こっちで実験してみたら全部綺麗にCSVでまとまってますが。
1ページ目、って「いせだ動物クリニック」から「小笠原家畜診療所」までですよねぇ。

> 1ページ目がの末尾が「?page=1」となっていないためForで抽出できていないのかな?と思いました。
> 1ページ目はfor文では回せないということでしょうか?

いや、そんな事はないです。
"?page=1"は、トップページと内容が同じなんで省略されてるだけ、ですね。だからfor文で回す対象にして構いません。
実際は、具体的に(動物病院のデータが載ってる)ページ全体が完全なテキストファイル(あるいはhtmlファイル)として4ページ分存在してるわけじゃなくって、それは簡単に言うと、裏側で走ってるデータベースに問い合わせしてるだけなんですね。例えば、新しく動物病院が開業しました、ページで紹介しなければって言った場合、「全部のページを一々書き換える」わけにはいかないじゃないですか(一々表示を移動して追加する、とか)。そりゃさすがにメンド臭いんで、そうすると、データベースにデータを「追加」するだけで、全てのページが「更新」されるように見せかけなきゃならないわけです。"?"ってのは要するに、ここからデータベースにクエリを投げて、ページにデータが追加されて更新されて書き換えられたように「見せてる」だけなんです。

考えられるのは、コピペした際に住所を得る部分

h2_tags = soup.find_all("h2", class_="shop_name")
shop_names += [tags.a.text for tags in h2_tags]

で何かおかしな事が起こったんですかねぇ。
「Webスクレイピング Google Co」の回答画像6
    • good
    • 0
この回答へのお礼

コピペした部分を手打ちし直したところうまく行きました!
丁寧にご回答および質疑応答までしていただきありがとうございました、本当に助かりました。
勉強を頑張りますので、また困った時は教えていただけますと幸甚です。

お礼日時:2020/07/27 17:51

あー、一応確認しておきますが、Google Colaboratoryをローカルで実行できるように設定してるんですかね?



ローカル ランタイム:
https://research.google.com/colaboratory/local-r …

これを設定してるなら、ローカルで走らせる事は可能な模様ですが・・・・やりました?
    • good
    • 0
この回答へのお礼

ありがとうございます。fromが3つ連なっていると頃に「from pydrive.auth import GoogleAuth」と入れてみたところエラーが起きなくなりました。

無事にドライブにCSVとして保存することができました!
ただし1ページ目の住所が抽出できない症状が出てしまっているようです。
URLをチェックすると下記のようになっていました。

1ページ目
https://petlife.asia/hospital/search/aomori/
2ページ目
https://petlife.asia/hospital/search/aomori/?pag …
3ページ目
https://petlife.asia/hospital/search/aomori/?pag …
4ページ目
https://petlife.asia/hospital/search/aomori/?pag …

1ページ目がの末尾が「?page=1」となっていないためForで抽出できていないのかな?と思いました。
1ページ目はfor文では回せないということでしょうか?
1ページ目を単独で実行し、それに加えてfor i in range(1, 4):page_url 、、、とする必要があるでしょうか。

何度も質問してしまい申し訳ありません。

お礼日時:2020/07/26 18:19

> すみませんもう一点ですが、from pydrive.drive import GoogleDrive〜のところですが、実行すると「NameError: name 'GoogleAuth' is not defined」とのエラーが出てしまいます。

なぜでしょうか

ん?変ですね。こっちでチェックする限りエラーにはならないんですが・・・・・・。
ええと、ローカルで実行してないですよね?Google Colaboratory( https://colab.research.google.com/notebooks/welc … )上で実行する限りそこではエラーが起きない筈ですが・・・・・。
ローカルで実行してるとすると、単純にpydriveと言うライブラリがインストールされていない、って意味になるんですが、いずれにせよ、参照ページ( https://colab.research.google.com/drive/1P1yGfCE … )の指針は、ローカルのPCで動かす為のコード指南ではなくって、あくまでGoogle Colaboratory上で実行するスクリプトの書き方、を指南しています。
    • good
    • 0

> for i in range(1,5):の段から実行しますと、下記のエラーが出てきます。



あ、コピペしたでしょ?
教えてgooの仕様だと、http://で始まるウェブアドレスがあまり長い場合には、省略されて表示されちまうんですよ(苦笑)。だからコピペそのまますると、文字列状態で末尾が"..."となって不完全なアドレスになっちまう(苦笑)。教えてgoo上でクリックしてリンク先に飛ぶ際には問題ないようになってますが、プログラムファイルにコピペすると甚だ不具合ですよねぇ。クソ、さすが「教えてgoo」はよく出来てる(出来てない・怒)。

ええとね、スクレイピング目的のサイト

https://petlife.asia/hospital/search/aomori/

を見てほしいんですが、下の1、2、ってページ移動を適当にクリックしてみてください。当然2ページ目に移動したり3ページ目に移動したりしますよね。その際、アドレスバーに注目してください。上のサイトアドレスに、例えば2ページ目だったら

?page=2

とか、3ページ目だったら3、とか付け足されてませんか?

つまり、上のアドレスの文字列に?page=を付け足して、forで回したi(つまり、さっきのプログラム上だと1~4までの数値になる)を文字列に変換(strによって)して足せば、自然と1ページ目から4ページ目までどんどん開いていく、ってことになります。

従って、教えてgooの仕様のせいで

?pag …

になってるとこは、

?page="

です。そこを修正してください。
    • good
    • 0
この回答へのお礼

ありがとうございます。その部分を解決することができました!
すみませんもう一点ですが、from pydrive.drive import GoogleDrive〜のところですが、実行すると「NameError: name 'GoogleAuth' is not defined」とのエラーが出てしまいます。なぜでしょうか

お礼日時:2020/07/26 17:32

あれ、冒頭の



import requests, csv

from bs4 import BeautifulSoup

が何故か抜けてましたね。すみません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!