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

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

ただいまの
回答率

87.48%

Python Webスクレイピング URLを変更して順番にスクレイピングしていきたい。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,968

score 25

Pythonを初めて数日の初心者で、プログラミングも勉強始めたばかりです。
最終的にWebスクレイピングができるようになりたいと思っています。

検索してもわからなく、つまづいているので詳しい方教えて下さいm(__)m

※Windows10のコマンドプロンプトから実行しています。
※Webスクレイピングの規約は確認しています。

★やりたいこと★

指定したURLのページから全ての画像を取り出すコードを作成したのですが、
URLの部分を変更して

CSVにリスト化したURLを順番にスクレイピングしていきたい。
C:\python/tabelog.csv

その後はフォルダ分けもやっていけたらと思っています。

■問題■

ForでLoopすることぐらいしか分からず
どこにどう追加していいか検討もつきません。。。
ほんとにすいません。ヒントでもいただけると本当に助かります。

■参考にしているサイト■
https://hashikake.com/scraping_img#source

★使用しているコード★

#●画像ファイルをダウンロードするための準備
# ①-①.ライブラリをインポート
import time
import re
import requests
from pathlib import Path
from bs4 import BeautifulSoup
# ①-②.出力フォルダを作成
output_folder = Path('C:\python\img')
output_folder.mkdir(exist_ok=True)
# ①-③.スクレイピングしたいURLを設定
url = 'https://tabelog.com/tokyo/A1303/A130302/13219514/dtlmenu/'

# ①-④.画像ページのURLを格納するリストを用意
linklist = []

#●検索結果ページから画像のリンクを取り出す
# ②-①.検索結果ページのhtmlを取得
html = requests.get(url).text
# ②-②.検索結果ページのオブジェクトを作成
soup = BeautifulSoup(html, 'lxml')
# ②-③.画像リンクのタグをすべて取得
a_list =soup.select('div.rstdtl-menu-lst__img')

# ②-④.画像リンクを1つずつ取り出す
for a in a_list:
# ②-⑤.画像ページのURLを抽出
    link_url = a.img['src']
# ②-⑥.画像ページのURLをリストに追加
    linklist.append(link_url)
    #time.sleep(1.0)

    # ③-⑦.画像ファイルの名前を抽出
    filename = re.search(".*\/(.*png|.*jpg)$",link_url)
    # ③-⑧.保存先のファイルパスを生成
    save_path = output_folder.joinpath(filename.group(1))
    time.sleep(1.0)
    # ●画像ファイルのURLからデータをダウンロード
    try:
        # ④-①.画像ファイルのURLからデータを取得
        image = requests.get(link_url)
        # ④-②.保存先のファイルパスにデータを保存
        open(save_path, 'wb').write(image.content)
        # ④-③.保存したファイル名を表示
        print(save_path)
        time.sleep(1.0)
    except ValueError:
        # ④-④.失敗した場合はエラー表示
        print("ValueError!")


宜しくお願いします。

頂いた回答を参考にもう1度コードを書いてみたのですが、次は1種類しか画像が取得できなくなりました。

エラーは出ません。
もう1度見ていただいてもよろしいでしょうか。

#●画像ファイルをダウンロードするための準備
# ①-①.ライブラリをインポート
import time
import re
import requests
from pathlib import Path
from bs4 import BeautifulSoup

# 出力フォルダを作成
output_folder = Path('C:\python\img')
output_folder.mkdir(exist_ok=True)

# スクレイピングしたいURLを設定
import pandas as pd

csv_file = r"C:\python\tabelog.csv"
df = pd.read_csv(csv_file)
# NOTE: df.列名.tolist()で指定列をリスト化する
url_list = df.URL.tolist()

# 画像ページのURLを格納するリストを用意
linklist = []

for url in url_list:
    # ②-①.検索結果ページのhtmlを取得
    html = requests.get(url).text
    # ②-②.検索結果ページのオブジェクトを作成
    soup = BeautifulSoup(html, 'lxml')
    # ②-③.画像リンクのタグをすべて取得
    a_list =soup.select('div.rstdtl-menu-lst__img')

    # ②-④.画像リンクを1つずつ取り出す
    for a in a_list:
        # ②-⑤.画像ページのURLを抽出
        link_url = a.img['src']
        # ②-⑥.画像ページのURLをリストに追加
        linklist.append(link_url)
        time.sleep(1.0)

        # ③-⑦.画像ファイルの名前を抽出
        filename = re.search(".*\/(.*png|.*jpg)$",link_url)
        # ③-⑧.保存先のファイルパスを生成
        save_path = output_folder.joinpath(filename.group(1))
        time.sleep(1.0)
    # ●画像ファイルのURLからデータをダウンロード
    try:
    # ④-①.画像ファイルのURLからデータを取得
        image = requests.get(link_url)
    # ④-②.保存先のファイルパスにデータを保存
        open(save_path, 'wb').write(image.content)
    # ④-③.保存したファイル名を表示
        print(save_path)
        time.sleep(1.0)
    except ValueError:
    # ④-④.失敗した場合はエラー表示
        print("ValueError!")

このコードの結果↓
10499
C:\python\img\150x150_square_83722393.jpg
10499
C:\python\img\150x150_square_83722393.jpg

です。何度もすいません。
宜しくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

過去の回答よりCSVは下のイメージです。

,店舗名,URL,点数
0,アンジェロ,https://tabelog.com/tokyo/A1301/A130101/13015364/,3.26
1,鳥元 虎ノ門店,https://tabelog.com/tokyo/A1308/A130802/13019433/,3.19
2,佐賀牛グリルイタリアン ドルチェヴィータ 銀座,https://tabelog.com/tokyo/A1301/A130101/13168844/,3.06
3,個室×ラクレットチーズ プラチナフィッシュ ガーデンキッチン ,https://tabelog.com/tokyo/A1301/A130103/13199175/,3.10

(中略)

18,本格中華食べ放題 天香府 新橋本店,https://tabelog.com/tokyo/A1301/A130103/13186435/,3.22
19,尾崎牛焼肉 銀座 ひむか,https://tabelog.com/tokyo/A1301/A130101/13193861/,3.54

csvからURLを抜き出す方法はいくつかありますが古い回答に倣いPandasを使ってみます。
上のCSVと相違点があればお手元のCSVにあわせてコードを書き換えてください。

import pandas as pd

csv_file = r"C:\python\tabelog.csv"
df = pd.read_csv(csv_file)
# NOTE: df.列名.tolist()で指定列をリスト化する
url_list = df.URL.tolist()

url_listを抜き出せたらforにかけて1つずつURLを取り出していきます。

for url in url_list:
    html = requests.get(url).text
    soup = BeautifulSoup(html, 'lxml')
    (以下略) 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/01 13:16

    イメージタグは取得できていました。前回教えてもらったコードで実行すると全部取得できるのですが、最後の1個だけしか取得できずです。すいません。原因が自分でわからず。。Forの中にあるからでしょうか(´;ω;`)。ぽんこつですいません。
    宜しくお願いします。

    キャンセル

  • 2020/04/01 13:29

    「# ●画像ファイルのURLからデータをダウンロード」の付近のインデントを確認してみましょう。Forで処理したいものはForのインデントに入れるようにします。

    キャンセル

  • 2020/04/01 14:12

    できましたーーーーーーーーー感涙。。こんなにもインデントって大事なんですね・・あぁ嬉しいです。
    涙。。。付き合ってくださり本当にありがとうございます。

    キャンセル

0

前回のhttps://teratail.com/questions/250473の応用で、こちらで頂いていたアンサーではimg_listの中に複数入っていた画像リンクを一つずつ取り出すfor文を書きましたよね?

今度はそれを用意しているURLの個数文繰り返しループ処理していけば良いと思います。
例として

#対象のURLが5個あったとする
target_list = ['http://hoge.net/A0123/123/dlmenu',
    'http://hoge.net/B0123/123/dlmenu',
    'http://hoge.net/C0123/123/dlmenu',
    'http://hoge.net/D0123/123/dlmenu'/,
    'http://hoge.net/E0123/123/dlmenu'
]

#target_listから一つずつurlを取り出しスクレイピング
for url in target:
    html = requests.get(url).text
    soup = BeautifulSoup(html, 'lxml')

    img_list =soup.select('div.rstdtl-menu-lst__img img')
    for img in img_list:
        link_url = img['src']


繰り返し処理(for文)の中で、更に繰り返し処理を行う事で実現に近づけるかと思います。

追記

import time
import re
import requests
from pathlib import Path
from bs4 import BeautifulSoup
from tqdm import tqdm

output_folder = Path('C:\python\img')

url_list = ['https://tabelog.com/tokyo/A1303/A130302/13219514/dtlmenu/',
            'https://tabelog.com/tokyo/A1303/A130302/13212082/dtlmenu/']

for url in url_list:
    html = requests.get(url).text
    soup = BeautifulSoup(html, 'lxml')
    a_list =soup.select('div.rstdtl-menu-lst__img')
    shopname = soup.find(class_='display-name').find_next('a').text

    for a in tqdm(a_list):
        link_url = a.img['src']
        filename = re.search(".*\/(.*png|.*jpg)$",link_url)
        save_path = output_folder.joinpath(shopname + filename.group(1))

        try:
            image = requests.get(link_url)
            open(save_path, 'wb').write(image.content)
        except ValueError:
            print('valueerror')
        time.sleep(2.0)
    time.sleep(2.0)


あくまでもサンプルコードとなります。
また質問者様の追記コードではお店毎にフォルダ分け等はしていない様で、どの画像がどのお店のものであるかの区別がつかない為、ファイル名にお店の名前をつける様な形のコードと勝手にさせていただきましたが不要であれば17行目、22行目のjoinpath部を削除してください。
あとtqdmも勝手に装飾してしまいました。installしてみて試してください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/01 12:49

    回答ありがとうございますm(__)m皆様の回答を参考にしながら、コード修正してみたのですが、エラーは出ないのですが、画像が1種類しか取得できなくなってしまい行き詰っています。質問分に新たに追加したので、恐縮ですが見ていただけると嬉しいです。

    宜しくお願いします。

    キャンセル

0

URLを順番にスクレイピングしていきたい。

まずは、変更したい変数を「関数の引数」にします。

# モジュールのインポート等は関数の外。
# 一度しか行わない処理はファイル先頭の方に記述

def download(url):
    # 以下に現在のコードを、適切なインデントで記述

    # ①-④.画像ページのURLを格納するリストを用意
    linklist = []

    ...

CSV 読込部分

import csv

# 文字コード "utf-8" のファイルを開く。
with open("tabelog.csv", encoding="utf-8") as stream:

    # CSV の1行目にヘッダがあり、読み飛ばしたい場合 
    # next(stream)

    # CSV のカラムは タイトルとURL を想定
    for title, url, in csv.reader(stream):

        # 進捗表示、今どこをダウンロード中か表示する場合
        # print("download {}".format(title))

        download(url)

文字コードや CSV読み込み時のオプション、
CSVの1行目にヘッダがある場合等、詳細は実際のCSVの内容に応じて変わります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/01 12:49

    回答ありがとうございますm(__)m皆様の回答を参考にしながら、コード修正してみたのですが、エラーは出ないのですが、画像が1種類しか取得できなくなってしまい行き詰っています。質問分に新たに追加したので、恐縮ですが見ていただけると嬉しいです。

    宜しくお願いします。

    キャンセル

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

  • ただいまの回答率 87.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る