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

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

ただいまの
回答率

89.24%

スクレイピングのコードでURLを取得する方法。

解決済

回答 1

投稿 編集

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

Egoil

score 18

スクレイピングのコードを書いていたら途中で詰まってしまいました。

childに何も格納されていないのでそこが原因かと思いますが、hrefの属性指定してURLを格納するようにgetメソッドを書いたのに何故だ。。。と混乱しております。
解答よろしくお願いします。

#coding:utf-8

import os
from bs4 import BeautifulSoup
import requests

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

import time

from urllib import request

import random

def make_randname():
    source_str = '#$%&0123456789abcdefghijklmnopqrstuvwxyz'
    random.choice(source_str)  #a〜zでランダムに1文字
    name = "".join([random.choice(source_str) for x in range(20)])
    return name + ".jpg"


def getimg(link):
    opener=request.build_opener()
    opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36')]
    request.install_opener(opener)
    # リンク先(一覧から一回飛んだページ)のContent-Body を取得する
    print("anal")
    response = requests.get(link)
    body = response.content
    soup = BeautifulSoup(body,"lxml")
    a_tags = soup.find_all("a", target="_blank")
    for a_tag in a_tags:
        try:
            src = a_tag["href"]
            name = src.split("/")[-1]
            if name.find(".jpg") < 0: break
            name = make_randname()
            request.urlretrieve(src, "./eroimages/"+name)
            print("[success]: {}".format(name))
            time.sleep(0.05)
        except:
            print("[failed]: {}".format(name))

def geturl(link):
    print("###############################################")
    #print("Page: {}".format(i))
    # リンク先(一覧から一回飛んだページ)のBodyを取得する
    aponse = requests.get(link)

    # HTML をパースする
    soup = BeautifulSoup(aponse.text, "lxml")
    links = soup.find_all('a')
    #print(links+"\n")
    for link in links:
        #title = link.find("strong")
        child = link.get("href")
        print("-----------------------------------------------")
        #print("Title: {}".format(title.string))
        print(child)
        getimg(child)

def main():
    if not os.path.exists("./eroimages"):
        os.mkdir("./eroimages")
    for i in range(1,2):
        link = "http://hnalady.com/page-{}.html".format(i)
        geturl(link)

if __name__ == "__main__":
    main()

スクレイピング先のHTMLソースは
view-source:http://hnalady.com/page-0.html
です。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

画像をダウンロードするのが目的であれば、img タグの src 属性を探せばいいかと思います。

以下、サンプルコードを貼ります。

import os
import random
import string
import time
import requests
from urllib.parse import urlparse

from bs4 import BeautifulSoup


def make_randname():
    letters = string.ascii_uppercase + string.digits
    return ''.join([random.choice(letters) for x in range(20)])


def get_img(url):
    print('fetching images from {}'.format(url))
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36'}
    res = requests.get(url, headers=headers)  # 子ページを取得する。
    soup = BeautifulSoup(res.text, 'lxml')

    # img タグを探して、ダウンロードする。
    for img_tag in soup.find_all('img', src=True):
        img_url = img_tag['src']
        print('downlaoding image... ', img_url)

        parsed_url = urlparse(img_url)
        ext = os.path.splitext(parsed_url.path)[1]  # 拡張子抽出
        save_path = os.path.join('images', '{basename}{ext}'.format(
            basename=make_randname(), ext=ext))

        # 画像をダウンロードして、保存する。
        img = requests.get(img_url).content
        with open(save_path, 'wb') as f:
            f.write(img)
        print('image saved ', save_path)

        time.sleep(0.5)  # 画像取得間隔


def get_url(url):
    print('fetching html... ', url)
    res = requests.get(url)
    soup = BeautifulSoup(res.text, 'lxml')

    for a_tag in soup.findAll('a', href=True):
        get_img(a_tag['href'])
        time.sleep(1)  # 子ページへのアクセス間隔


def main():
    os.makedirs('images', exist_ok=True)
    for i in range(1, 2):
        url = 'http://hnalady.com/page-{}.html'.format(i)
        get_url(url)


if __name__ == '__main__':
    main()

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/10/29 17:50

    hrefでURLを取るよりもsrcでとったほうがいいということでしょうか?

    キャンセル

  • 2018/10/29 18:08 編集

    質問欄のコードを拝見したところ、子ページの一覧を取得して、アクセスする→子ページの画像をまとめて保存する」となっていたので、まず soup.findAll('a', href=True) でリンク一覧を抽出してその各ページにアクセスし、soup.find_all('img', src=True) で画像一覧を取得するようにしています。

    リンク一覧をとるなら、仰る通り a タグの href をとればよいです。
    画像のリンクをとるなら、img タグの src をとればよいです。

    キャンセル

  • 2018/10/29 19:48 編集

    なるほど!そういう事ですか。
    すみません、僕のコード、childにURLが格納されなかったんですけど何か理由とかお分かりだったりしますか。。?

    キャンセル

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

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