🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
スクレイピング

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

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Python

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

1603閲覧

Pythonのスクレイピング(SUUMOから物件情報を取り出す)途中でエラーが発生する

sakihokusho

総合スコア0

スクレイピング

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

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Python

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2020/11/24 00:59

Pythonのスクレイピング(SUUMOから物件情報を取り出す)がうまくいかない

SUUMOから物件情報をスクレイピングしたいのですが、どうしても途中で”ページを表示できません”となってしまいます。
最初の数ページ分の情報を取り出せているので、コード自体に間違いはないと思うのですが…
超初心者が見様見真似で始めたものなので、原因が思い当たらず困っております。

発生している問題・エラーメッセージ

AttributeError Traceback (most recent call last) <ipython-input-49-ccef615dab50> in <module> 32 soup = BeautifulSoup(c, "html.parser") 33 summary = soup.find("div",id ='js-bukkenList') ---> 34 houses = summary.find_all('li', class_='cassette js-bukkenCassette') 35 36 for house in houses: AttributeError: 'NoneType' object has no attribute 'find_all'

該当のソースコード

Python

1!pip install beautifulsoup4 2from bs4 import BeautifulSoup 3import re 4import requests 5import time 6import pandas as pd 7!pip install lxml 8print('done') 9 10url = 'https://suumo.jp/jj/common/ichiran/JJ901FC004/?initFlg=1&seniFlg=1&ar=030&ta=13&scTmp=13103&scTmp=13109&scTmp=13110&scTmp=13111&scTmp=13112&scTmp=13113&ct=9999999&cb=0.0&kt=8000&kb=0&xt=9999999&xb=60&md=7%2C8%2C9&md=10%2C11%2C12&md=13&et=7&cn=25&newflg=0&km=1&sc=13103&sc=13109&sc=13110&sc=13111&sc=13112&sc=13113&bs=010&bs=011&bs=020&bs=021&pc=100' 11result = requests.get(url) 12c = result.content 13soup = BeautifulSoup(c,"html.parser") 14 15summary = soup.find("div",{'id':'js-bukkenList'}) 16body = soup.find("body") 17pages = body.find_all("div", {'class':'pagination pagination_set-nav'}) 18pages_text = str(pages) 19pages_split = pages_text.split('</a></li></ol>') 20num_pages = int(pages_split[0].split('>')[-1]) 21print("ページ数=",num_pages) 22urls = [] 23urls.append(url) 24 25for i in range(num_pages - 1): 26 page_num = str(i + 2) 27 url_page = url + '&pn=' + page_num 28 urls.append(url_page) 29 30data = [] 31 32jenre = '' #物件タイプ 33name = '' #物件名 34price = '' #購入価格 35address = '' #住所 36station = '' #最寄駅 37walk = '' #バス徒歩 38area = '' #土地面積 39building = '' #建物面積 40floor_plan = '' #間取り 41monthly = '' #月々の支払い 42age = '' #築年数 43link = '' #リンク 44kanrihi = '' #管理費 45shuzenhi = '' #修繕積立費 46reform = '' #リフォーム 47total_units = '' #総戸数 48right_form = '' #権利形態 49right_district = '' #用途地域 50parking = '' #駐車場 51 52for url in urls: 53 54 result = requests.get(url) 55 c = result.content 56 soup = BeautifulSoup(c, "html.parser") 57 summary = soup.find("div",id ='js-bukkenList') 58 houses = summary.find_all('li', class_='cassette js-bukkenCassette') 59 60 for house in houses: 61 jenre = house.find_all('span', class_='ui-pct ui-pct--util1 cassettebox-hpct cassettebox-hpctcat')[0].string 62 name = house.find_all("a", class_='js-cassetLinkHref')[0].string 63 price = house.find_all('dd', class_="infodatabox-details-txt")[0].string 64 address = house.find_all('div', class_='infodatabox-box-txt')[0].string 65 station = house.find_all('div', class_='infodatabox-box-txt')[1].string 66 walk = house.find_all('div', class_='infodatabox-box-txt')[2].text 67 area = house.find_all('dd', class_="infodatabox-details-txt")[2].text 68 69 detail = house.find_all('div', class_='infodatabox-box-txt')[4] 70 cols = detail.find_all('dd', class_='infodatabox-details-txt') 71 for i in range(len(cols)): 72 if len(cols) == 2: 73 building = detail.find_all('dd', class_='infodatabox-details-txt')[0].string 74 floor_plan = detail.find_all('dd', class_='infodatabox-details-txt')[1].string 75 elif len(cols) == 3: 76 building = detail.find_all('dd', class_='infodatabox-details-txt')[1].text 77 floor_plan = detail.find_all('dd', class_='infodatabox-details-txt')[2].string 78 79 monthly = house.find_all('dd', class_="infodatabox-details-txt")[1].string 80 age = house.find_all('div', class_='infodatabox-box-txt')[5].string 81 linkbox = house.find('div', class_='cassettebox-action') 82 linked = linkbox.find('a') 83 links = linked.get('href') 84 link = 'https://suumo.jp' + links 85 86 87 link_child = link + 'bukkengaiyo/' 88 result_child = requests.get(link_child) 89 c_child = result_child.content 90 soup_child = BeautifulSoup(c_child, 'html.parser') 91 summary_child = soup_child.find_all('tbody',{'class':'vat tal'}) 92 93 try: 94 kanrihi = summary_child[0].find_all('td')[5].string.strip('\r\n\t') 95 shuzenhi = summary_child[0].find_all('td')[6].string.strip('\r\n\t') 96 reform = summary_child[0].find_all('td')[16].contents 97 total_units = summary_child[1].find_all('td')[2].string.strip('\r\n\t') 98 right_form = summary_child[1].find_all('td')[5].string.strip('\r\n\t') 99 right_district = summary_child[1].find_all('td')[6].string.strip('\r\n\t') 100 parking = summary_child[1].find_all('td')[7].string.strip('\r\n\t') 101 except: 102 pass 103 104 string = [jenre, name, price, address, station, walk, area, building, floor_plan, monthly, age, link, kanrihi, shuzenhi, reform, total_units, right_form, right_district, parking] 105 data.append(string) 106 107 time.sleep(1) 108 109df = pd.DataFrame(data, columns=['物件タイプ','物件名','購入金額','住所','最寄駅','バス徒歩','土地面積','建物面積','間取り','月々支払額','築年数','URL','管理費','修繕積立費','リフォーム','総戸数','権利形態','用途地域','駐車場']) 110df.to_csv('suumo_scrape.csv', sep=',', encoding='utf-8', header=True, index=False)

試したこと

物件の詳細ページを開いてさらに情報を取り出す行程(link_child = link + ...以降の部分)を加える前は、情報を取り出してCSV形式で保存するところまで問題なく完了できたのですが、件のコードを追加してからは途中までしかスクレイピングが進まず、途方に暮れております。
time.sleep()で間隔を開けてみたりしたのですが、やはり途中で止まってしまいます。

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

Jupyter Notebookを使用しております。

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

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

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

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

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

tetsunosuke

2020/11/24 01:24

先程、いただいたプログラムを動かしてみましたが問題なく動きました。 > AttributeError: 'NoneType' object has no attribute 'find_all' ということで、summaryがNoneだったのだと思います、つまり div の idがjs-bukkenListがなんらかの理由で取得できなかったのでしょう。 そのときのURLをprintしてみるなりして、実際の画面のHTMLのコードを見てみるとなにかわかるかもしれません。
sakihokusho

2020/11/24 02:02

早速見ていただいてありがとうございます! そうなんです、SummaryがNoneになるのですが、URLを辿るとhtmlのコード上に”ページが表示できません”と出ておりまして… 今気付いたんですが、Javascriptの設定が有効になっていないとも出ているので、こちらを何とかすれば良さそうな気もしてきました。
tetsunosuke

2020/11/24 02:18

requestsではあくまでも文字列としてデータを取得し、それをBeautifulSoupで解析する、という流れなのでJavaScriptは有効にはならないですね。 なんとかする・・・headlessなブラウザが操作できるseleniumあたりになるでしょうか。
sakihokusho

2020/11/24 23:18

アドバイス頂いた通りselenium試そうとしていますが、PATHが通らなかったりと苦労しております。 ひとまず問題がわかりましたので、もう少し悪戦苦闘してみます。ありがとうございます。
tetsunosuke

2020/11/25 00:35

driver = webdriver.Chrome(executable_path='〜') とか明示的に指定すればそこまで困らないかなとは思いますが、ひとまずそれで引き続き試してみてください この質問が完了なのであれば状況を回答に記載して自己解決としてください。
guest

回答1

0

自己解決

Javascriptが有効になっていない事が原因でした。
止まってしまったURL先のhtmlコードを見に行ったら発見できました。
ありがとうございました。

投稿2020/11/25 00:38

sakihokusho

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問