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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Beautiful Soup

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

Python

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

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

2回答

1215閲覧

python3 BS4 find_all で<li>をスタイル(width)で判別、見出しと値の辞書を作成するには

dub

総合スコア23

Beautiful Soup

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

Python

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

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

0クリップ

投稿2021/07/22 00:46

編集2021/07/22 02:20

Python3 beautiful soup4 で スクレイピングしているのですが
IDが元ソースに付与されておらず、取得したい部分が<li> </li>ばかりで、またページにより 項目数<li>の数が変わるので、決まった値を取得するのに難航しています。

唯一  styleでwidth 40 width60 とで 見出しと値が対になって判別できる為
これを見出しと値を 対にして 辞書型にすれば解決できるのではと思いました。

html

1<ul> 2 3<li style="width: 40%;">見出し1</li> 4<li style="width: 60%;">値1</li> 5<li style="width: 40%;">見出し2</li> 6<li style="width: 60%;">値2</li> 7<li style="width: 40%;">見出し3</li> 8<li style="width: 60%;">値3</li> 9<li style="width: 40%;">見出し4</li> 10<li style="width: 60%;">値4</li> 11<li style="width: 40%;">見出し5</li> 12<li style="width: 60%;">値5</li> 13 14</ul>
<li><li>タグではなくテーブルタグ <th></th> <tr></tr>で見出しと値が対になっている場合は 下記方法でできるので、これを応用して<li>のスタイル width 40 width 60% で判別してできないかと考えたのですが・・ ```HTML thとtdが見出しと値で対になっている場合はできる dict={} for tag in soup.find_all(['th', 'td']): if tag.name == 'th': key = tag.get_text() elif tag.name == 'td': dict[key] = tag.get_text() ```

おなじようにliタグのスタイル  width 40 or width60  で判別して
見出し と値で辞書にしたいです

やってみたこと

Python

1dict={} 2for tag in soup.find_all([('li',style="width: 40%;"), ('li',style="width: 60%;")]): 3 if tag.name == ('li',style="width: 40%;"): 4 key = tag.get_text() 5 elif tag.name == ('li',style="width: 60%;"): 6 dict[key] = tag.get_text()

if tag.name == ('li',style.value'width: 40%;'):
^
SyntaxError: invalid syntax

python

1dict={} 2for tag in soup.find_all([soup.find_all('li' ,style=lambda value: value and 'width: 40%;' in value and 'width: 60%;' in value)]): 3 if tag.name == ('li',style.value'width: 40%;'): 4 key = tag.get_text() 5 elif tag.name == ('li',style="width: 60%;"): 6 dict[key] = tag.get_text()

エラー内容
File "<ipython-input-51-b737eb51cd68>", line 3
if tag.name == ('li',style.value'width: 40%;'):
^
SyntaxError: invalid syntax

##この方法に拘っていませんが・・
※参照元ページは各ページで <li>の数が異なるのでsoul.select でCSSセレクターで取得すると、各ページで変数に入る値が異なるので、見出しをキーにして値を取り出したいです

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

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

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

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

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

guest

回答2

0

ベストアンサー

python

1 patternA = 'width: 40%;' 2 patternB = 'width: 60%;' 3 4 lst = soup.find_all('li') 5 for element in lst: 6 if element.get('style') == patternA: 7 # patternAだった場合の処理 8 elif element.get('style') == patternB: 9 # patternBだった場合の処理
`.find_all()`を使用する際にオプションでstyleを指定してあげても良いでしょうが 上記の様にまずはli要素を取得してから、for文でstyle属性を検証していく手もあるでしょう。 > ※参照元ページは各ページで <li>の数が異なるのでsoul.select でCSSセレクターで取得すると、各ページで変数に入る値が異なるので、見出しをキーにして値を取り出したいです どの様なページなのかはわかりませんがコツとしては li要素から探すよりも、そもそもそれらul要素を包み込んでいる 大元にある要素や属性を指定していくと余計なli要素を拾わず対象の要素だけを検証出来るでしょう。

投稿2021/07/22 08:06

nto

総合スコア1438

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

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

dub

2021/07/22 09:39

ヒントをありがとうございます! なるほど、for文を使うとは考えつきませんでした。いただいたヒントをもとに 条件別の処理で 辞書を作ってみたところ、目的の辞書を作ることができました dict={} patternA = 'width: 40%;' patternB = 'width: 60%;' lst = soup.find_all('li') for element in lst: if element.get('style') == patternA: key = element.get_text() elif element.get('style') == patternB: dict[key] = element.get_text()
nto

2021/07/23 08:50

肝心なエラーの原因について説明をしておりませんでした。 例えばif tag.name == ('li',style.value'width: 40%;'):について やりたい事はなんとなくわかります。 この様な記述は、BeautifullSoupを使用してソースをパースしたものに対して使用出来る記述となります。 パースしたものが変数soupとなります。 変数soupの中からli要素且つstyle属性がwidth: 40%となっているものを探してねーという指示を行いたい場合には、変数soupに対してfind_all()というメソッドを使用します。 soup.find_all() 括弧の中に引数として検索したい条件を与えていきます。li要素を指定したいならば soup.find_all('li')と指定します。 更にstyle属性なども指定していきたい場合には soup.find_all('li', {'style': 'width: 40%;})という様に指定していきます。 これは第一引数にli要素を指定し、第2引数にStyle属性と指定の値を辞書形式で与えているというものとなります。 あくまでもこれは.find_all()メソッドに対して引数を与えているというものであり dubさんが書いていたif tag.name == ('li',style.value'width: 40%;'):というのは あくまでもタプルでしかない為、コードの意味としては もしも タグネームが ('li', style.value'width: 40%;') というタプルと同じだったら~ という条件式になってしまっており、またそのタプル自体もタプルとして機能していない為にシンタックスエラーが生じてしまっているのです。
guest

0

  • Syntax Errorの原因

('li',style="width: 40%;")

というtupleの後ろの要素のところに代入式を書いていることです。

理由
tupleと、関数などの呼び出しに与える引数リストは別物です。
引数リストの場合、name=argumentと書けますが、これはキーワード付引数です。

  • 見出しをキーにして値を取り出したいです

htmlを使う場合、構造を意識した書き方もあれば、表現を意識した書き方もあります。
テーブルタグを使ったものは構造を意識したhtmlですのでBeautifulSoupで処理しやすいですが、今回の場合のように構造を意識しない書き方の場合にはBeautifulSoupで処理するのは難しいでしょう。

Pythonで一次元配列を二次元配列に変換(numpy.ndarray、リスト) を参考にして考えてみてください。

投稿2021/07/22 04:38

ppaul

総合スコア24666

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

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

dub

2021/07/22 09:41

ありがとうございます!まだnumpyを使った事がないくらいの超初心者なので、numpy勉強してみます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問