冒頭文だけ少し書きます。
Webスクレイピングの勉強中に出会ったパッケージです。
日本語での情報が少ないので、日本語で活用方法を備忘録的に残しておきたいがために書いています。
■BeautifulSoup
HTMLを解析して扱いやすくしてくれるモジュールです。
公式リンクhttps://www.crummy.com/software/BeautifulSoup/bs4/doc/
例:こんな感じで使う
これはhttps://news.ycombinator.com/ (ニュースサイト)で表示される30個の記事の中から最も評価の高い記事のタイトルとリンクを表示するプログラムです。
from bs4 import BeautifulSoup
import requests
response = requests.get("https://news.ycombinator.com/")
yc_response = response.text
soup = BeautifulSoup(yc_response,"html.parser") #html.parserはコンテンツがhtmlであることをpythonに宣言する役割
article = soup.find_all(name="a", class_="titlelink")
article_texts = [] #text(title)を格納
article_links = [] #linkを格納
for article_tag in article:
text = article_tag.getText() #テキストを取得する
article_texts.append(text) #テキストをリストに追加する
link = article_tag.get("href") #リンクを取得する
article_links.append(link) #リンクをリストに追加する
article_upvote = [int(score.getText().split()[0]) for score in soup.find_all(name="span", class_="score")]
largest_number = max(article_upvote)
largest_index = article_upvote.index(largest_number)
print(article_texts[largest_index])
print(article_links[largest_index])
■コンテンツを取得する
上記例より引用。対象となるwebページを取得し、変数に格納、BeautifulSoupに投げる
import requests
response = requests.get("https://news.ycombinator.com/")
response_text = response.text
soup = BeautifulSoup(response_text, "html.parser") #html.parserはコンテンツがhtmlであることをpythonに宣言する役割
・ローカルに保存してあるhtmlファイルを開くなら以下のように
公式にはencodingは指定されていないけど、日本語のページなら必要
with open("website.html", encoding="utf-8", mode="r") as file:
contents = file.read()
soup = BeautifulSoup(contents, "html.parser")
■要素毎に一番初めに出てくるものを取得する(a,li,p など
print(soup) #取得したHTML全体が表示される
print(soup.prettify()) #取得したHTML全体が[* インデントを含めて]表示される
print(soup.title) #一番初めにある<title>~~~~~~~~~~~</title>全部表示される
print(soup.title.name) #titleと表示される
print(soup.title.parent.name) #headと表示される ※一番初めのタイトルはほとんどの場合headの配下にあるため。
print(soup.title.string) #タイトルテキストが表示される

print(soup.a) #一番初めにあるアンカータグ<a>~~~</a>が表示される
print(soup.li) #一番初めにあるリスト<li>~~~</li>の項目が表示される
print(soup.p) #一番初めにあるパラグラフ<p>~~~</p>が表示される
■find・ID指定で要素を取り出す
()内のクエリにマッチする1番初めの要素を取り出す
heading = soup.find(name="h1", id="name")
・classを使って取り出す要素を指定する
class_はPythonの予約語出ないことを示すため_が必要
section_heading = soup.find(name="h3", class_"heading")
print(section_heading.get("class")) #一応クラス名の取得もできる ["heading"]のように表示される
・例:inputに含まれる属性変数を取り出す
(HTML)<input type = "text" name= "q" maxlength="255" value="">
のようなHTMLがあり、maxlengthの内容を取得したいとする。
from_tag = soup.find("input")
max_length = from_tag("maxlength") #255が取得できる
■find_all・一番初め以外のものも取得したい場合
all_anchor_tags = soup.find_all(name="a") # list形式ですべてのアンカー(a)要素を取得
for tag in all_anchor_tags:
print(tag.getText()) #テキストだけ表示
print(tag.get("href")) #アンカータグのリンクを表示
■select・マッチする項目をすべて表示
print(soup.select("title")) #titleを表示 [<title>~~~</title>]
■select_one・マッチした項目の1番最初だけ表示
company_url = select_one(serection="p a")
#上記例だと、HTML内の<p>~<a>~</a>~</p>のようにParagraphの中にAnchorが含まれている要素を取り出すことができる。
・CSSのIDを指定するなら
name = soup.select_one(serection = "#name") ##id名
活用例として、膨大な情報が含まれているwebページの場合、セクションごと(要するにごと)にidが含まれていることが多いため、対象のdivの内側だけを対象にする時に使用する。
・CSSのclassを指定するなら
heading = soup.select(".heading") /.クラス名
■スクレイピングは節度を守るように
・robots.txt https://developers.google.com/search/docs/advanced/robots/intro?hl=ja
robots.txtはクローラ(情報収集のために動いているプログラムなど)に対して過負荷を避けるために使用されます。
このブログにも設定されているようです
このように末尾に”/robot.txt”を入力すると以下のような内容が表示されます。
User-agent: *
Allow: /wp-admin/admin-ajax.php
Disallow: /wp-admin/
Sitemap: https://rbelgblog.com/sitemap.xml
Sitemap: https://rbelgblog.com/sitemap.rss
Sitemap: https://rbelgblog.com/sitemap.xml
意外と参考になりませんね・・・とりあえず、許可されているものと、禁止されているものが設定されているページと認識ください。
冒頭の例で挙げたサイトにも設定されているようなので少し見ると
Crawl-delay: 30
このような1文が見つかりました。ループ処理などによって連続して負荷を与えないようにしなければならないということですね。その他、禁止されているものがいくつかあります。
上記のサイトは比較的寛容なほうです。禁止事項が多かったり、規約で禁止されているサイトではスクレイピングをしないようにしましょう。
■スクレイピングをできないようにするには
サイトを運営する側の視点の話をすると、禁止事項の存在や、規約を読まずに知らないユーザがスクレイピングを行いDDoS攻撃になってしまうということも考えられます。
規約があり、摘発できれば、裁判に持ち込めば、そのユーザに高い授業料を支払わせることはできますが、運営側もリソースを割く必要があり、1つ1つ潰していくには骨が折れます。
あるべき論でいえば、スクレイピングができない環境にすべきです。
方法
①reCAPTCHAを使ってプログラミングからの自動操作を行えないようにする。
②ファイル自体にパスワードを掛ける ※これは組織内の秘密情報に対する策
③APIを公開し、情報の取得はAPI経由で行ってもらうようにする。
とはいえ、技術も日々成長していくものなので、やめてほしいスクレイピングを完全に禁止することは難しいのも事実です。
※指摘、誤字脱字があれば連絡頂けると嬉しいです。


コメント