python3.doc_33
R e i - D r e a m
for Laravel
TOP > Python3 > ライブラリ(BeautifulSoup)
Guest
login

最終投稿日:2022年6月18日

ライブラリ(BeautifulSoup)
スクレイピングによる解析ライブラリ
※Anaconda3 を入れていればあります
基本的な使い方は、HTML 文と、パーサー文字列を引数にインスタンスを生成します。
例)
soup = BeautifulSoup(html, 'html.parser')
※HTML 文を解析する場合は「'html.parser'」を使う
※ライブラリ「urllib」の『request.urlopen(url) 』で取得したものを使う(read メソッドは不要)
○ HTML 構造から取得する
v = soup.html.body.h1                                                      ※最初の h1 タグの内容を取得できる
v = soup.html.body.p                                                         ※最初の p タグの内容を取得できる
v = soup.html.body.p.next_sibling.next_sibling    ※最初の p タグの次の要素を取得できる
v.string で要素内の文字列のみを取得できる(v だけだとタグ付きとなる)
【注意】
next_sibling は次の要素を取得するための変数ですが、1つだけ指定すると基本的なサイトの作りとして
改行文字とかになる可能性が高いので、2回記述しています。
なのでサイトの作りが<p>hoge</p><div>foo</div><span>bar</span>と、連続して記述してある場合に
hoge の要素に対して next_sibling を2回記述すると bar が取得されます。
○ find メソッドから取得する
v = soup.find(id='hoge')             ※id 属性 hoge の値を取得する
v = soup.find(class_='hoge')    ※class 属性 hoge の値を取得する
v = soup.find('title')                     ※title タグの値を取得する
v.string
v.contents[i]    ※多重構造になっている中身を取得できる。例)<span class="important">8,800<small>円</small></span>
          上記で【8,800】を取得したい場合、span タグを find し、v.string としても、small タグも内包しているため取得できません。
          その様な場合は、v.contents[0] とすると取得できます。
○ find_all メソッドから取得する
links = soup.find_all('a')            ※リンク等はサイト内に複数あるのでこのメソッドが使えます。
links = soup.find_all("a", class_="link", href="/link")      ※classがlinkでhrefが/linkのaタグをすべて取得する
または、
links = soup.find_all("a", attrs={"class": "link", "href": "/link"})
for a in links:
    link = a.attrs['href']            ※A タグの href 属性の内容を取得できる(要するにリンク URL)
    text = a.string                       ※A タグの要素を取得できる
    tag = a.name                        ※タグの要素名を取得(DIV とか)
【メモ】
上記の様に a.attrs['href'] で URL を取得できますが、解析元の URL が相対で記述されている場合は、当然相対 URL のまま取得できます。
これを絶対 URL にするには urllib.parse ライブラリの urljoin メソッドを使うと良い。
○ select_one メソッドで CSS セレクタを使い値を1つ取得する
v = soup.select_one('div#meigen > h1')      ※id=meigen を持つ div タグ内の h1 タグの値を取得する
v.string
○ select メソッドで CSS セレクタを使い値を複数取得する
     ※id=meigen を持つ div タグ内の class=items を持つ ul タグ内の li タグの値を全て取得する
v = soup.select('div#meigen > ul.items > li')
for li in v:
    li.string                                          ※ループで各値を取得できる
【メモ】
セレクタを自動で生成する方法があります。
クロムの場合は F12 で解析画面を表示し、取得したいコード上で右クリックし Copy -> Copy selector を選択します。
以下はペーストしたサンプル
    #main > div.stocksDtlWp > div > div.forAddPortfolio > table > tbody > tr > td
上記サンプルをそのままセレクタとして利用できます。
ただし、なぜか tbody が混ざってるとエラーとなってしまったので注意!
上記サンプルでは以下の様に tbody を抜いてエラーを回避しました。
例)
    soup.select_one('#main > div.stocksDtlWp > div > div.forAddPortfolio > table > tr > td')
○ その他のメソッド(prettify)
値を整形する。
soup = BeautifulSoup(html, 'html.parser')
print(soup.prettify())
上記の様に prettify メソッドを使って表示するとタブ等の間隔も綺麗に表示してくれます
セレクタ表
● セレクタの基本式
*全ての要素
要素名要素名の要素      例)div
.クラス名クラス名
#id名id名
● セレクタ同士の関係を指定する書式
セレクタ, セレクタ列挙された複数のセレクタ      例)h1, h2
セレクタ セレクタ下の階層の子孫要素      例)div h1
セレクタ > セレクタ直下の階層の子要素      例)div > h1
セレクタ + セレクタ同じ階層で直後に隣接している要素      例)h1 + h2
セレクタ1 ~ セレクタ2セレクタ1からセレクタ2までの要素      例)p~ul
● セレクタの属性による指定書式
要素[att]特定の属性名を持つ要素
要素[att='val']att 属性に val という値を持つ要素
要素[att~='val']att 属性の値候補 val(スペース区切り)に一致した要素
要素[att | ='val']att 属性の値が val で始まる要素(ただしハイフン区切り)
要素[att^='val']att 属性の値が val で始まる要素
要素[att$='val']att 属性の値が val で終わる要素
要素[att*='val']att 属性の値を含む要素
要素:rootルートとなる要素
要素:nth-child(n)n 番目の子となる要素
要素:nth-last-child(n)後ろから n 番目の子となる要素
要素:nth-of-type(n)n 番目のその種類の要素
要素:first-child子として最初の要素
要素:last-child子として最後の要素
要素:first-of-type最初のその種類の要素
要素:last-of-type最後のその種類の要素
要素:only-child子として唯一の要素
要素:only-of-type子として唯一の種類の要素
要素:empty要素内容が空となる要素
要素:lang(code)特定の言語に code を指定された要素
要素:not(s)s 以外の要素
要素:enabled有効となっている UI 要素
要素:disabled無効となっている UI 要素
要素:checkedチェックされている UI 要素
【注意】
BeautifulSoup では、nth-child 等のセレクタには対応していません。
その代わり nth-of-type で代用できます。
(おそらく~type となっているのが代用できるセレクタです。。)
ログインしてコメントを残そう!!


きっぷる