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

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

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

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

Q&A

解決済

1回答

2484閲覧

[Python3]BeautifulSoup4でのスクレイピングについて

kurosuke___

総合スコア217

Python 3.x

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

0グッド

0クリップ

投稿2016/06/01 11:55

こんにちは。いま、Python、スクレイピング、クローラの勉強のために、i〇〇〇ページをスクレイピングしようと試みています。
使用しているpythonは3.5、BeautifulSoupは4を使っています。

対象のwebサイトは1ページの中に、

店舗名 住所 電話番号

といった形のブロックが多数あります。
同じような感じで、店舗名,住所,電話番号という順番で、ページ内のすべてをcsvに出力したいと思っています。

したいこと:
電話番号がないブロックがまれにあるため、そのままだと次のブロックの電話番号が詰められてしまいますよね?なので、ないところは半角ハイフンを入れたいです。

備考:
住所は全て〒から始まるので、textの指定で引っこ抜いています。

下記のHTMLのarticleタグが一つのブロックで、1ページに50ブロックあります。

html

1<body> 2 <div> 3 4 <article> 5 <section> 6 <h4><a href="URL">店舗名</a></h4> 7 <p><span>~</span>住所<a>~</a></p> 8 <p><span>~</span><a>~</a><b>電話番号</b></p> 9 <p>~</p> 10 </section> 11 </article> 12 13 </div> 14</body>

sectionタグ内のpタグの数はブロックによって変わります。
(URLの記載がある場合はpタグが一つ増えます。電話番号がないブロックは、pタグが一つ減ります。)

現状:

Python

1from urllib.request import urlopen 2from bs4 import BeautifulSoup 3import re 4 5html = urlopen("URL") 6bsObj = BeautifulSoup(html,"html.parser") 7 8titles = bsObj.body.find_all("h4",{"class":"clearfix"}) 9adrss = bsObj.body.find_all(text=re.compile("〒")) 10numbs = bsObj.body.find_all("b") 11 12 13for (title,adrs,numb) in zip(titles,adrss,numbs): 14 print(title.get_text()) 15 print(adrs) 16 print(numb.get_text())

Python初心者の上、BeautifulSoupの使い方もよくわからないです・・・
find_allを二階つづけてつかうことはできないのでしょうか・・・

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

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

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

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

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

guest

回答1

0

ベストアンサー

find_allを二階つづけてつかうことはできないのでしょうか・・・

そうですね、find_allした結果のオブジェクトResultSetには、find_allが無いのでできません。

基本的な「塊」を取り出したら、あとは相対指定やselectメソッドで取り出すほうが簡単です。

下記の例では、「塊」のarticlefind_allして取り出した複数のarticleに対して、個別の処理を書くようにしてみました。
だいぶ雑なので、細かいところは調整してみてください。

lang

1articles = bsObj.body.find_all("article") 2 3for x in articles: 4 shop_name = x.section.h4.text 5 pa = x.section.select('p') 6 address = pa[0].text 7 tel = pa[1].b.text 8 print('shop_name = %s, address = %s, tel = %s' % (shop_name, address, tel)) 9 # shop_name = 店舗名, address = ~住所~, tel = 電話番号

投稿2016/06/01 14:39

argius

総合スコア9388

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

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

kurosuke___

2016/06/02 16:46

なるほど、find_allにはそういう性質がありましたか… selectやループを駆使してやると良いようですね。 argiusさんのコードを参考にできたので、わからずに躓く状態を抜け出せました。ありがとうございます。 大変助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問