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

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

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

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

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

799閲覧

BeautifulSoupを用いたスクレイピングにおける条件の設定について

lilliveon

総合スコア9

Beautiful Soup

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

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2023/09/24 11:07

編集2023/09/24 11:19

実現したいこと

スクレイピングで画像/動画作品を収集する際、各Webページにアクセスした時に、作品が表示される場合は取得し、表示されない場合は取得しないようにしたい。

前提

閲覧頂きありがとうございます。
現在、danbooruというイラスト投稿サイトにおいて、特定のタグが付与されている作品を収集するソースコードを作っています。

下部に掲示しているソースコードの仕組みについて説明します。
まず以下のページのhtmlをrequestしたあとに作品を収集します。
https://danbooru.donmai.us/posts/6681790?q=sylveon
その後、nextクラスにある次のページのhtmlをrequestして作品を収集します。
https://danbooru.donmai.us/posts/6680502?q=sylveon
そしてまたnextクラスにある次のページのURLをrequestして作品を収集するというのを繰り返してスクレイピングを行います。

そして、danbooruの特徴として、R18である一部の作品は「Disable all」を押さないと表示されないようになっています。2つ目のURLの次のページは下記のURLであり、表示されない作品ページに該当いたします。
https://danbooru.donmai.us/posts/6655703?q=sylveon 【閲覧注意】
この作品ページは左上にある「Disable all」を押すことで作品を表示できるようになります。

その上で私のやりたいことは、3つ目のURLにあるような、表示を制限されているR18作品は収集しないように設定することです。現状のソースコードでは、表示を制限されている作品であろうとなかろうと収集してしまいます。

上記のことを実現するためのお力添えをいただきたいです。よろしくお願い致します。

該当のソースコード

Python

1import requests 2from bs4 import BeautifulSoup 3import os 4import time 5 6output_dir = "danbooru_img/sylveon" 7end_times = 10000 8url = "https://danbooru.donmai.us/posts/6681790?q=sylveon" 9 10for page in range(end_times): 11 response = requests.get(url) 12 13 if not os.path.exists(output_dir): 14 os.makedirs(output_dir) 15 16 soup = BeautifulSoup(response.text, "html.parser") 17 18 try: 19 source = soup.find("img", id="image").get("src") 20 except AttributeError: # 作品が画像ではなく動画である場合はエラーが発生するのでこちらを実行 21 source = soup.find("video").get("src") 22 23 img = requests.get(source) 24 25 with open(f"{output_dir}/{source.split('/')[-1]}", 'wb') as f: 26 f.write(img.content) 27 28 time.sleep(1) 29 30 next = soup.find("a", class_="next").get("href") 31 url = f"https://danbooru.donmai.us/{next}" #次のページのURLを作成 32

試したこと

調べてみた結果、Seleniumを使うと実現できるのではないかと思いました。ですが、その場合は動作が遅くなるデメリットがあるためできるだけ使用したくありません。
JavaScriptの動作が関係しているのではと思いましたが、JavaScriptの知識が全くなく、開発者ツールで見てみてもソースコードがあまりにも多い&複雑すぎて見当がつきません。

補足情報

Python==3.11.5
requests==2.31.0
beautifulsoup4==4.12.2

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

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

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

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

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

guest

回答1

0

ベストアンサー

Rating: Explicitの場合は data-raging="e" が付与されるようなので、それを除けば良さそうです。

python

1image = soup.select_one('#content section.image-container:not([data-rating="e"]) img#image') 2if image is not None: 3 source = image.get("src")

投稿2023/09/24 11:46

Eggpan

総合スコア3255

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

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

lilliveon

2023/09/24 13:27 編集

回答ありがとうございます。 いただいたいコードを自分なりに実装してみたのですが、こちらで合っていますでしょうか? ``` import requests from bs4 import BeautifulSoup import os import time output_dir = "danbooru_img/sylveon" end_times = 10000 url = "https://danbooru.donmai.us/posts/6681790?q=sylveon" for page in range(end_times): response = requests.get(url) if not os.path.exists(output_dir): os.makedirs(output_dir) soup = BeautifulSoup(response.text, "html.parser") # try: # source = soup.find("img", id="image").get("src") # except AttributeError: # 作品が画像ではなく動画である場合はエラーが発生するのでこちらを実行 # source = soup.find("video").get("src") image = soup.select_one('#content section.image-container:not([data-rating="e"]) img#image') if image is not None: source = image.get("src") img = requests.get(source) with open(f"{output_dir}/{source.split('/')[-1]}", 'wb') as f: f.write(img.content) print(source) time.sleep(1) next = soup.find("a", class_="next").get("href") url = f"https://danbooru.donmai.us/{next}" # 次のページのURLを作成 ``` このソースコードの場合、確かにR18画像は収集しなくなるのですが、同時に動画作品の収集もできなくなってしまいました。改善案がございましたら教えてくださると嬉しいです。よろしくお願いします🙇‍♂
Eggpan

2023/09/24 12:44

先に画像か動画かを判断する必要があるのではないでしょうか?
lilliveon

2023/09/24 13:26 編集

お返事ありがとうございます。 仰る通りで、元のソースコードではコメントアウトしてある部分で判断していましたが、ご教授いただいたやり方の場合はどのように設定すれば分からず困っています... 現在何とかしようと頑張っているのですが、 image = soup.select_one('#content section.image-container:not([data-rating="e"]) img#image') の#というのはどういう意味なのでしょうか...? CSSに関係するのかと思ったらそうでもなさそうで、#contentが解析したhrmlのどこにも無く、検索しても上手くヒントを得られずに困っています。
Eggpan

2023/09/24 13:27

select_oneはcssセレクタを利用します。#はid指定ですので、 #contentは id="content" を表します。 image_tag = soup.find("img", id="image") として、if image_tag is not None などで処理を分けられないでしょうか。
lilliveon

2023/09/24 15:42

無事解決いたしました。 アドバイスいただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問