MENU
  • ホーム
  • プログラミング
  • ワードプレス
    • プラグインプラグイン関連記事
    • 賢威賢威のカスタマイズ
    • CSSCSSの関連記事
  • サイト情報
    • プライバシーポリシー
  • ツール
    • メルエディター
    • フリマスパイダー – 疾風
    • フリマスパイダー
    • -ポイ活くんα-
  • お問い合わせ
あらゆるモノにHackする、探究者の読み物。
Let's Hack Tech
  • ホーム
  • プログラミング
  • ワードプレス
    • プラグインプラグイン関連記事
    • 賢威賢威のカスタマイズ
    • CSSCSSの関連記事
  • サイト情報
    • プライバシーポリシー
  • ツール
    • メルエディター
    • フリマスパイダー – 疾風
    • フリマスパイダー
    • -ポイ活くんα-
  • お問い合わせ
Let's Hack Tech
  • ホーム
  • プログラミング
  • ワードプレス
    • プラグインプラグイン関連記事
    • 賢威賢威のカスタマイズ
    • CSSCSSの関連記事
  • サイト情報
    • プライバシーポリシー
  • ツール
    • メルエディター
    • フリマスパイダー – 疾風
    • フリマスパイダー
    • -ポイ活くんα-
  • お問い合わせ
  1. ホーム
  2. プログラミング
  3. 言語別
  4. Python
  5. BeatufulSoup でウザすぎる改行コード”\n”を駆逐する

BeatufulSoup でウザすぎる改行コード”\n”を駆逐する

2023 2/02
Python
2019-09-012023-02-02
Beautiful Soup

BeautifulSoupでスクレイピング中にクラス等の配置がなく、どうしても直で要素指定が出来ず、回り込んで兄弟要素指定をしたい時があります。

そんな時に何故か要素の間に出現している謎の改行コード”n”を駆逐する方法です。

目次

BeatufulSoupで直指定が出来ない要素

BeatufulSoupで直指定が出来ない要素

例えばこんな感じのデータテーブル、データリストなんかが特にクラスやID指定なんかがないパターンが多いです。

中でも厄介なのが<dl><dt><dd>のデータリストタイプ。

<table><th><tr><td>のデータテーブルタイプであればpandasのread_htmlメソッドでURLを指定するだけで一発で抜き出せる荒業が使えるのですが、データリストタイプにはread_htmlは反応しません。

必然、n番目の~、や特定の文字列●●を持つ次の~、など一回りした間接的な指定にならざるを得ません。

BeatufulSoupで間接的に要素を指定してみる

クラスなどが直上のクラスに含まれているパターンに比べて少し面倒にはなりますが、もちろん実現できます。

<dl class="dl-horizontal">
  <dt>落札価格</dt>
  <dd>
    <span class="canopy-large-value">¥4,000</span>
  </dd>
  <dt>ランク</dt>
  <dd>
    <span class="canopy-large-value">AB</span>
  </dd>
  <dt>落札日</dt>
  <dd>2019/08/28</dd>
  <dt>市場</dt>
  <dd>2019年8月第88回オークション(2019/8/28)</dd>
  <dt>タイプライン</dt>
  <dd>
  </dd>
  <dt>カテゴリー</dt>
  <dd>バッグ</dd>
  <dt>形状コード</dt>
  <dd>
    トートバッグ </dd>
  <dt>付属品コード</dt>
  <dd>
    – </dd>
  <dt>型番</dt>
  <dd>
  </dd>
</dl>

例えばこのようなHTMLの場合であれば<dd>タグの中身が欲しいことがほとんどだと思います。

逆に<dt>タグの中身は全てのページに共通しているのが普通の構造です。

このパターンであれば<dt>タグのテキストで検索→ヒットしたテキストから親要素→その要素の兄弟要素、という経路で取得するのがベストかと思います。

BeatufulSoupで実際に取得してみる

例えば、上のソースコードの「落札日」が目的だった場合。

from bs4 import BeautifulSoup
soup = BeautifulSoup(res.content, 'lxml')

# テキストで検索すると、テキスト本体が返ってくる
In:soup.find(text='落札日')
Out: '落札日'

# parentでタグまで戻る
In:soup.find(text='落札日').parent
Out: <dt>落札日</dt>

# 更に次の兄弟要素を取得する
In:soup.find(text='落札日').parent.next_sibling
Out: 'n'
# ここで↑想定外の改行コード出現

# ちなみに、更に次の兄弟要素で目的のタグが出現します
In:soup.find(text='落札日').parent.next_sibling.next_sibling
Out: <dd>2019/08/28</dd>

謎の位置に改行コードが出現しました。ソース上それらしきものは全く見られないにもかかわらずです。

実はこれスクレイピングでは結構あるあるというか、日常だったりします。

Soupオブジェクトから余計な改行を削除する

このように、間接的な要素の指定によるデータ取得が多くなりがちなサイトではBeautifulSoupのインスタンス生成の直後に、改行を根こそぎ駆逐しておくのが良いかと思います。

from bs4 import BeautifulSoup
soup = BeautifulSoup(res.content, 'lxml')
# これを追加↓
[tag.extract() for tag in soup(string='n')]

soupオブジェクトのrootに対して(string=改行)としてfind_allしています。
それを更にリスト内包表記で要素をぶん回してextract()で根こそぎ削除、というのが上のコードです。

これでタグからはみ出して兄弟の間に割り込んでくるウザい改行コード”n”が死滅します。

注意点として、改行を削除しても、文字列が分断された構造は保持されたままになりますので、soup.a.string のような形で取得しようとすると見た目にstringが取れそうでもNoneが返却されてくるパターンがあります。

何のこと言ってんだ?って方はこちらも是非合わせて読んでみてください。

あわせて読みたい
BeautifulSoupでstringとtextの挙動の明確な違い – Python soupオブジェクトに対して".string"や".text" で文字列を抽出することが出来ますが、両者の明確な挙動の違いを例を挙げて紹介します。

まとめ

ちなみに、<dd>タグ内が全部ほしいなら素直にsoup(‘dd’)でいいんですけどね。

今回は要らなかったので、ちょっと回りくどいですが、こんな方法もありますよという事で。

Python
BeautifulSoup
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする コメントをキャンセル

email confirm*

post date*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

シンプル美と機能性を両立させた、国内最高峰のWordPressテーマ『SWELL』
人気記事
  • IQテストいくつか受けてみました
    ネット上で信憑性がありそうなIQテスト、5種類まとめて受けた結果…
  • hayate
    メルカリの商品を世界最速で購入するためだけのアラートツール
  • 【Python】BeautifulSoupの使い方・基本メソッド一覧|スクレイピング
  • Pythonファイルのexe化
    【悲報】PyInstallerさん、300MBのexeファイルを吐き出すようになる
  • Amazon Echo アレクサのコマンドまとめ
    AmazonEchoの使い方とできる事、アレクサへの指示コマンド一覧
最近の投稿
  • 正規表現処理の濁点でハマった話2024-12-12
  • 保護中: 疾風v2更新履歴2024-05-31
  • 【自営・経営者向け・税金も】クレジットカードガチ勢による最強クレカ解説2023-10-23
  • PyQt5 QListWidget の item削除でtextBoxのフォーカスが奪われる2023-03-05
  • WordPressからのメールが届かない時の調査と解決法2023-02-27
目次
目次