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

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

新規登録して質問してみよう
ただいま回答率
85.49%
スクレイピング

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

Beautiful Soup

Beautiful Soupは、Pythonのライブラリの一つ。スクレイピングに特化しています。HTMLデータの構文の解析を行うために、HTMLタグ/CSSのセレクタで抽出する部分を指定することが可能です。

Python

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

Q&A

解決済

3回答

3413閲覧

python スクレイピング 'NoneType' object is not subscriptableの解決

rururan

総合スコア1

スクレイピング

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

Beautiful Soup

Beautiful Soupは、Pythonのライブラリの一つ。スクレイピングに特化しています。HTMLデータの構文の解析を行うために、HTMLタグ/CSSのセレクタで抽出する部分を指定することが可能です。

Python

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

0グッド

0クリップ

投稿2020/05/14 14:46

前提・実現したいこと

pythonで、ファッションサイトから情報をスクレイピングするシステムを作っています。
bs4オブジェクトから名前を取得中にエラーが起きていると思うんですが。。。
修正するべき場所がわからず。。。力をお貸しいただければと思います。
実行コマンドは
$ python main.py
です。

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

'''PS C:\brandrecommend\brand_recommend> python main.py
C:\brandrecommend\brand_recommend\scrayping.py:17: UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("lxml"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.

The code that caused this warning is on line 17 of the file C:\brandrecommend\brand_recommend\scrayping.py. To get rid of this warning, pass the additional argument 'features="lxml"' to the BeautifulSoup constructor.

return BeautifulSoup(res.text)
Traceback (most recent call last):
File "main.py", line 19, in <module>
NameList.extend(getNameList(snaps))
File "C:\brandrecommend\brand_recommend\scrayping.py", line 33, in getNameList
NameList.append(snap.find('a')['title'])
TypeError: 'NoneType' object is not subscriptable'''

###該当のソースコード

python

1scrayping.py 2 3# -*- coding: utf-8 -*- 4 5import re 6 7import numpy as np 8from bs4 import BeautifulSoup 9import requests 10import pandas as pd 11import collections 12 13# URLからbs4オブジェクトを生成 14def openURL(URL: int): 15 res = requests.get(URL) 16 if res.status_code != requests.codes.ok: 17 print('Error') 18 return(False) 19 return BeautifulSoup(res.text) 20 21 22# bs4オブジェクトから着用ブランドのリストを取得 23def getBrandList(snaps): 24 BrandList = [] 25 for snap in snaps: 26 BrandList.append(list(set(map(lambda x: x.text, snap.find_all( 27 'a', attrs={'href': re.compile('^/snaps/brand')}))))) 28 return BrandList 29 30 31# bs4オブジェクトから名前を取得 32def getNameList(snaps): 33 NameList = [] 34 for snap in snaps: 35 NameList.append(snap.find('a')['title']) 36 return NameList 37 38 39def getuniqueList(df): 40 uniqueList = [] 41 42 for columns in df.columns.values: 43 uniqueList.extend(df[columns]) 44 45 return collections.Counter(uniqueList)

python

1main.py 2 3from scrayping import * 4from predict import * 5from predict2 import * 6 7if __name__ == '__main__': 8 flag = True 9 page = 1 10 BrandList = [] 11 NameList = [] 12 13 while flag: 14 URL = 'https://www.fashion-press.net/snaps/sex/mens?page=' + str(page) 15 soup = openURL(URL) 16 snaps = soup.find_all(attrs={'class': 'fp_media_tile'}) 17 18 if len(snaps) != 0: # 写真がある場合はブランドを取得 19 tmpBrandList = getBrandList(snaps) 20 BrandList.extend(tmpBrandList) 21 NameList.extend(getNameList(snaps)) 22 print('get page' + str(page)) 23 page += 1 24 25 else: # 写真がない場合は終了 26 flag = False 27 print('END') 28 29 df = pd.DataFrame(data=BrandList, index=NameList) # pandasのDataFrame型に 30 df.to_csv('StreetSnapMen.csv') 31 # df = pd.read_csv('StreetSnapMen.csv', index_col = 0) 32 33 brand = getuniqueList(df) 34 brand_df = pd.DataFrame(index=list(brand.keys()), 35 data=list(brand.values())) 36 brand_df = brand_df.drop(np.nan) # NAN を削除 37

python

1predict.py 2 3# -*- coding: utf-8 -*- 4 5import re 6 7import numpy as np 8from bs4 import BeautifulSoup 9import requests 10import pandas as pd 11import collections 12 13 14def bays(model, A, B=None): 15 pB = (model == B).sum().sum() 16 pAB = (((model == A) | (model == B)).sum(axis=1) > 1).sum() 17 return pAB / pB 18 19 20def predict(df, brand_df, wear, k=3): 21 prob = [] 22 23 for brand in brand_df.index: 24 prob.append(bays(df, brand, wear)) 25 26 best_k = sorted(range(len(prob)), key=lambda i: prob[i], reverse=True)[:k] 27 return list(map(lambda k: brand_df.index[k], best_k))

試したこと

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

windows10
python 3.8.2

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

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

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

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

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

meg_

2020/05/14 14:53

エラーが発生したときの「snap.find('a')」が「None」になってませんか?
rururan

2020/05/15 09:35

「snap.find('a')」では値が存在しますが、「snap.find('a')['title']」でnoneになりました。
guest

回答3

0

ベストアンサー

ファッション画像を挿入する div と広告枠の div のどちらもクラス fp_media_tile なのが原因ではないでしょうか。
ファション画像の div は <div class="fp_media_tile snap_media col_3">
広告枠の div は <div class="fp_media_tile advertisement_media col_3">
となっているので、CSS セレクタ .fp_media_tile.snap_media で絞ればいいと思います。

問題箇所

イメージ説明

html

1<div class="fp_media_tile advertisement_media col_3"> 2<!-- /8505930/FP_News_Index --> 3<div id="div-gpt-ad-1516356120429-0" style="margin: 0 auto;"> 4<script> 5 googletag.cmd.push(function() { googletag.display('div-gpt-ad-1516356120429-0'); }); 6 </script> 7</div> 8</div>

修正箇所

diff

1- snaps = soup.find_all(attrs={"class": "fp_media_tile"}) 2+ snaps = soup.select(".fp_media_tile.snap_media")

find() した結果は print() すると、HTML で表示できるので、それでデバッグしましょう。

投稿2020/05/15 12:49

tiitoi

総合スコア21956

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

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

rururan

2020/05/15 14:45

回答いただきありがとうございます!おっしゃる通りでした。 snaps を取得するときに、divタグの指定、及びclass名に漏れがあったのでそれを修正したところ無事にaタグ内のtitleの値を取得できました!
guest

0

下記でどうでしょうか?

Python

1def getNameList(snaps): 2 NameList = [] 3 for snap in snaps: 4 NameList.append(snap.find('a').get('title') 5 return NameList

【追記】

エラーが発生したときの「snap.find('a')」が「None」になってませんか?

質問への質問で上記を書きましたが、やはりエラーが発生する直前にNoneになっています。
aタグを取得できないsnapがあるのでしょう。確認してください。

投稿2020/05/15 10:52

編集2020/05/15 11:43
meg_

総合スコア10579

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

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

rururan

2020/05/15 11:21

そのパターンもやってみましたが、同じエラーでした… aタグだけのスクレイピングをしたところ、aタグ内にtitle属性は存在したのですが、title属性を指定したスクレイピングをするとnoneが帰りました。ちなみにhref属性もtitle属性同様、noneでした。
guest

0

そのパターンもやってみましたが、同じエラーでした…
aタグだけのスクレイピングをしたところ、aタグ内にtitle属性は存在したのですが、title属性を指定したスクレイピングをするとnoneが帰りました。ちなみにhref属性もtitle属性同様、noneでした。

投稿2020/05/15 11:18

rururan

総合スコア1

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問