teratail header banner
teratail header banner
質問するログイン新規登録
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2421閲覧

スクレイピングがうまくいかない

HirokiTomimura

総合スコア26

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/07/19 07:28

0

0

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
pythonでスクレイピングをしています
サイトのhtmlが不完全なのか?データの抽出がうまくいきません。

エラーメッセージ none
<div id="primary-navigation" data-bk-dynamic="primary-navigation"> <ul> <li class="current"> <a href="/index">TOP</a> </li> <li class=""> <a href="/地図">店舗一覧</a> </li> <li class=""> <a href="/スマホ119の評判">お客様の評判</a> </li> <li class=""> <a href="/iPhone修理ブログ">修理ブログ</a> </li> <li class=""> <a href="/ブログ">ブログ</a> </li> <li class=""> <a href="/スタッフ紹介">スタッフ紹介</a> </li> <li class=""> <a href="/求人募集">求人募集</a> </li> <li class=""> <a href="/水没修理">水没修理</a> </li> <li class=""> <a href="/アップデート失敗復旧">システム復旧</a> </li> <li class=""> <a href="/機種変更データ移行">データバックアップ</a> </li> <li class=""> <a href="/データ復元">データ復元</a> </li> <li class=""> <a href="/3DSゲーム機修理">3DS修理</a> </li> <li class=""> <a href="/Androidスマホ修理">Android修理</a> </li> <li class=""> <a href="/iPad修理">iPad修理</a> </li> <li class=""> <a href="/iPhone基盤修理">基盤修理</a> </li> <li class=""> <a href="/出張修理">出張修理</a> </li> <li class=""> <a href="/iPhone買い取り">買取り</a> </li> <li class=""> <a href="/保証"> 保証内容</a> </li> <li class=""> <a href="/お客様相談窓口">お客様相談窓口</a> </li> <li class=""> <a href="/パソコン修理">パソコン修理</a> </li> <li class=""> <a href="/腕時計電池交換">時計電池交換</a> </li> <li class=""> <a href="/会社概要">会社概要</a> </li> <li class=""> <a href="/沖縄市泡瀬店">泡瀬店</a> </li> <li class=""> <a href="/宜野湾ベース">宜野湾店</a> </li> <li class=""> <a href="/豊見城市とよみ店">とよみ店</a> </li> <li class=""> <a href="/うるま市石川店">石川店</a> </li> <li class=""> <a href="/うるま市うるま店">うるま店</a> </li> <li class=""> <a href="/イオン名護店">イオン名護店</a> </li> <li class=""> <a href="/糸満店">糸満店</a> </li> <li class=""> <a href="/西原店">西原店</a> </li> <li class=""> <a href="/イオンモール鹿児島店">イオンモール鹿児島店</a> </li> <li class=""> <a href="/那覇オーパ店">那覇オーパ店</a> </li> <li class=""> <a href="/ワイモバイル">Y!モバイル</a> </li> </ul> </div><!-- #primary-navigation --> <!-- </div> --!> <div id="content" class="clearfix">
python

試したこと

他のサイトでは、データが入っている部分をこのようにして抜け出しましたが、
main_body = soup.find("ul", {"class": "todouhukentop panel"})

今回のサイトの各ページへのリンク部分がどのようにしても抽出できません。
main_body = soup.find("div", {"id": "primary-navigation"})

このサイト:http://iphone119.xyz 自社サイトです。
真ん中のオレンジ部分の各ページへのリンクを抽出したい
そして、全ページのブログを抽出したい。

このサイトの場合はどのようにして、各ページのリンクを抽出すればよいのでしょうか?

はじめての質問です、質問の要領をつけめていない場合はすみません。
どうぞよろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

中央のオレンジのリンクを抽出でしたら

python

1import requests 2from bs4 import BeautifulSoup 3from urllib.parse import urljoin 4 5url = 'http://iphone119.xyz/' 6 7headers = { 8 'User-Agent': 9 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko' 10} 11 12r = requests.get(url, headers=headers) 13 14if r.status_code == requests.codes.ok: 15 16 soup = BeautifulSoup(r.content, 'html5lib') 17 18 for i in soup.select("#primary-navigation > ul > li > a"): 19 print(urljoin(url, i.get("href")))

投稿2019/07/20 09:59

barobaro

総合スコア1286

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

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

HirokiTomimura

2019/07/20 12:00

barobaroさん どうもありがとうございます! すごくシンプルに抽出出来ますね!! from urllib.parse import urljoin を使うやり方も勉強します。 どうもありがとうございます 今後ともどうぞよろしくおねがいします。
barobaro

2019/07/20 13:22

urljoinは抽出されたURLが相対アドレスのため urljoinを使いベースのURLと結合して絶対アドレスに変換しております
guest

0

ベストアンサー

行いたい事はどちらなのでしょうか?
・真ん中のオレンジ部分( div id="primary-navigation" 配下)の html(ソース)を取得したい
・真ん中のオレンジ部分の「店舗一覧」などをクリックした時の遷移先 URL(href)を取得したい

main_body = soup.find("div", {"id": "primary-navigation"})

これだと前者が取得できますが

各ページのリンクを抽出すればよいのでしょうか?

この質問にある「リンク」という言葉だと、URL(href)を連想させます。


あと、質問する際は実際のコードを記載した方が
回答しやすいかと思います。

★★★★★★★★
追記

「 URL(href)」を取得したいとのことですが、
この書き方では前者の「真ん中のオレンジ部分(div id="primary-navigation"配下)の html(ソース)」が返却されます。

そのため「 URL(href)」を取得するのであれば
この書き方に追加で href を取得していくためのコードが必要となります。

そちらは「 python href 取得 」などでググればすぐ出てくると思います。


ですが、そもそも find で div id="primary-navigation" 配下が取得できないとのことなので
そこを解消します。

まず、書き方は正しいです。
※ちなみに html ソース上にある <div id="main0">
同じ書き方 main_body = soup.find("div", {"id": "main0"}) で取得できています。

ですが確認したところ「 primary-navigation 」という文字が使用できないようで
そのため「 None 」と返却されているようです。

確認方法はこちらで行いました。
https://docs.python.org/ja/3/library/keyword.html

★訂正
すみません、何か勘違いしていました。
ローカルで <div id="primary-header" data-bk-dynamic="primary-header"> 配下のhtmlだけ抜粋し
試してみたところ「primary-header」でも取得できました。

では何が原因か探ったところ、<div id="primary-header"・・・の直前にある
コメントアウト部分が悪さをしているようです。

html

1<!-- <div class="panel panel-primary visible-lg"> --!> ★その1 2<div id="primary-navigation" data-bk-dynamic="primary-navigation"> 3 <ul> 4(略) 5 <a href="/ワイモバイル">Y!モバイル</a> 6 </li> 7 </ul> 8 </div><!-- #primary-header --> ★その2

この★その1と★その2の影響で、<div id="primary-navigation"・・・の中身ごと
コメントアウトとして認識されてしまい、データが取得されない
ということです。

https://ulnomad.com/2017/06/%E3%80%90html%E3%80%91%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%82%A2%E3%82%A6%E3%83%88%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9/#i-3
コメントの途中に「-(ハイフン)」が入っていると、ブラウザによっては表示に影響が出る可能性もあるので、コメントの途中でハイフンを入れないようにする。

解決方法としては
・そのそもの id 名「 primary-navigation 」を他の文字に変更する
1.html上で不正なコメントアウトを消す
→html修正が必要
2.「 primary-navigation 」を囲っている上(親)の要素から取得する
→今後のhref取得において、書き方によっては他の href も取得されてしまう
3.python のプログラムに <!-- <div class="panel panel-primary visible-lg"> を空に置換してあげる
→応急措置です。他にもこのような箇所があるため、本来であれば1のhtml記述不正の修正を行った方が良いです。

ちなみにコードはこれです。

python

1html_doc = requests.get("http://iphone119.xyz/").text 2html = html_doc.replace('<!-- <div class="panel panel-primary visible-lg"> --!>', '') #追加 3soup = BeautifulSoup(html, 'html.parser')

投稿2019/07/19 16:37

編集2019/07/20 07:35
pon_nyamo

総合スコア30

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

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

HirokiTomimura

2019/07/19 18:04 編集

pon_nyamoさん、どうもありがとうございます。 先ず行いたいのは、オレンジ部分の中にある、店舗毎の各ページへのURL(href)を取得したいのです。 失礼しました、実際のコードを記載します。 from bs4 import BeautifulSoup import requests from lxml import html html_doc = requests.get("http://iphone119.xyz/").text soup = BeautifulSoup(html_doc, 'html.parser') #print(soup.prettify()) main_body = soup.find("div", {"id": "primary-navigation"}) print (main_body) としましたが、 Noneと帰ってきてしまいます。
pon_nyamo

2019/07/20 04:31

返信遅くなりました。 上記回答に追記しましたので、ご確認お願いいたします。 また、記載ミスかと思いますが >html_doc = requests.get("http://iphone119.xyz/&quot;).text 「&quot;」だと特殊文字となるため「"」が正しいです。
HirokiTomimura

2019/07/20 06:14

追記ありがとうございます。 前者の方法が理想ですが、ブログ自体を触らないといけなくなるので 後者のやり方で進めたいと思っております そこで、親要素のid="wrap"で取り込みましたが やはり、余分な前後文がくっついてきました。 余分な上下を削除するにはどのようにしたら良いでしょうか? stripを使えばできそうだと、ググってわかったのですが、よくわかりません。 <div id="wrap"> <div class="hidden-sm hidden-xs" id="primary-header"> <a class="logo" href="/">iPhone 修理 沖縄で一番安くiPhone修理します。<br/>アイフォンのお医者さんスマホ119<br/></a> <dl> <dt>iPhone修理沖縄「スマホ119」</dt> 中略 読み込みたい部分 <div id="primary-navigation" data-bk-dynamic="primary-navigation"> <ul> <li class="current"> <a href="/index">TOP</a> </li> <li class=""> <a href="/地図">店舗一覧</a> </li> <li class=""> <a href="/スマホ119の評判">お客様の評判</a> </li> <li class=""> <a href="/iPhone修理ブログ">修理ブログ</a> </li> <li class=""> <a href="/ブログ">ブログ</a> </li> <li class=""> <a href="/スタッフ紹介">スタッフ紹介</a> </li> <li class=""> <a href="/求人募集">求人募集</a> </li> <li class=""> <a href="/水没修理">水没修理</a> </li> <li class=""> <a href="/アップデート失敗復旧">システム復旧</a> </li> <li class=""> <a href="/機種変更データ移行">データバックアップ</a> </li> <li class=""> <a href="/データ復元">データ復元</a> </li> <li class=""> <a href="/3DSゲーム機修理">3DS修理</a> </li> <li class=""> <a href="/Androidスマホ修理">Android修理</a> </li> <li class=""> <a href="/iPad修理">iPad修理</a> </li> <li class=""> <a href="/iPhone基盤修理">基盤修理</a> </li> <li class=""> <a href="/出張修理">出張修理</a> </li> <li class=""> <a href="/iPhone買い取り">買取り</a> </li> <li class=""> <a href="/保証"> 保証内容</a> </li> <li class=""> <a href="/お客様相談窓口">お客様相談窓口</a> </li> <li class=""> <a href="/パソコン修理">パソコン修理</a> </li> <li class=""> <a href="/腕時計電池交換">時計電池交換</a> </li> <li class=""> <a href="/会社概要">会社概要</a> </li> <li class=""> <a href="/沖縄市泡瀬店">泡瀬店</a> </li> <li class=""> <a href="/宜野湾ベース">宜野湾店</a> </li> <li class=""> <a href="/豊見城市とよみ店">とよみ店</a> </li> <li class=""> <a href="/うるま市石川店">石川店</a> </li> <li class=""> <a href="/うるま市うるま店">うるま店</a> </li> <li class=""> <a href="/イオン名護店">イオン名護店</a> </li> <li class=""> <a href="/糸満店">糸満店</a> </li> <li class=""> <a href="/西原店">西原店</a> </li> <li class=""> <a href="/イオンモール鹿児島店">イオンモール鹿児島店</a> </li> <li class=""> <a href="/那覇オーパ店">那覇オーパ店</a> </li> <li class=""> <a href="/ワイモバイル">Y!モバイル</a> </li> </ul> </div><!-- #primary-navigation --> <!-- </div> --!> 以下削りたい部分 <div id="content" class="clearfix"> <div id="main1"> <div id="bk-sheet-main1" class="bk-sheet" data-bk-sheet="main1" data-bk-common="0"> <div class="bk-blocks"><div id="bk-block-1631" class="bk-block BlockCode" data-bk-block-id="1631" data-bk-block-package="BlockCode"> <div class="bk-block-content"> <div class="bk-block-code-content"><a href="http://iphone119.xyz/スタッフ紹介"><img src="http://iphone119.xyz/pic/rotate.php" height="500px" width="" alt="スマホ119スタッフ紹介" /></a></div> </div> 中略 </div> <div class="bk-block BlockPhoto" data-bk-block-id="539" data-bk-block-package="BlockPhoto" id="bk-block-539"> <div class="bk-block-content"> <div class="bk-block-photo-box" id="bk-block-photo-image-539" style="text-align: center"> <div class="outer"><img id="bk-block-photo-image-539" src="/files/images/width/300/wnmAsfKB2BoVQIkV.png"/></div> </div> </div> </div> </div> </div> </div> 前と後ろの部分を削除するようなことは可能でしょうか? あと、primary-navigationが使えないようなのですが、 primary_navigationのようにアンダーバーに一旦まるまる読み込んで、 pytonで - を _アンダーバーに置き換えて、処理を進めるみたいなこともできるのでしょうか? 的はずれな質問でしたらすみませんが、よろしくおねがいします。
pon_nyamo

2019/07/20 07:32

回答に追記・修正しました。 「 primary-navigation 」という文字が使用できない というのは私の勘違いでした・・・。 大変失礼いたしました。 追記した通り、コメントアウトが悪さをしているようです。 本件が解決できるコードを記載しておりますので、試してみてください。 ----- ちなみに strip とか replace とかの使い方はこちらを参照してください。 https://qiita.com/tomotaka_ito/items/594ee1396cf982ba9887
HirokiTomimura

2019/07/20 11:58

追記、修正、どうもありがとうございます! 思っているような動作が出来ました! 丁寧に解説して頂きまして本当に助かりました。 周りには誰も相談できる人がいないので、このようなサイトが有ることを知って心強いです。 これからもよろしくお願いします。 strip replaceの使い方も調べて頂きありがとうございます。
pon_nyamo

2019/07/20 12:43

長々と失礼しました・・・・ >そのため「 URL(href)」を取得するのであれば >この書き方に追加で href を取得していくためのコードが必要となります。 > >そちらは「 python href 取得 」などでググればすぐ出てくると思います。 下記の方の回答ですでに解決したかもしれませんが こちらもググって実行してみて、詰まったらまた聞いてください^^ 私もpython勉強中ですのでお互い頑張りましょう~
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問