brown water

ゲームやアニメの感想とかプログラムとか

Pythonで画像スクレイピング&ダウンロード

前回の記事で使ったBeautifulSoupを応用して、今回は画像をスクレイピングしたいと思います。
スクレイピングするサイトですが、これも前に書いた記事Bashで画像ダウンロードで使用したサイトにします。

画像URLの取得

クラス名mdMTMWidget01ItemCite01Valueを探してリンク情報を取得します。

import requests
from bs4 import BeautifulSoup

url='https://matome.naver.jp/odai/2149130246521074801'
req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')
feeds = soup.find_all(class_='mdMTMWidget01ItemCite01Value')
for feed in feeds:
    print(feed.a.get('href'))

これでjpg画像のURLを取得出来ることが分かりました。

画像のダウンロード

sleepを使いたいのでインポートしておきます。

from time import sleep

先程のコードを多少変更して追加

count = 0
for feed in feeds:
    img_url = feed.a.get('href')
    img_file = requests.get(img_url)
    save_name = f'./test_{count:03}.jpg'    #保存場所とファイル名
    with open(save_name, 'wb') as f:
        f.write(img_file.content)
    sleep(1)
    count+=1

ダウンロードにはRequestsを使用します。
保存ファイル名を指定してファイルを書き込み、スリープを挟みながら処理していきます。

複数ページ処理については難しくないと思うので割愛。

まとめ

全コード

import requests
from bs4 import BeautifulSoup
from time import sleep

url='https://matome.naver.jp/odai/2149130246521074801'
req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')
feeds = soup.find_all(class_='mdMTMWidget01ItemCite01Value')

count = 0
for feed in feeds:
    img_url = feed.a.get('href')
    img_file = requests.get(img_url)
    save_name = f'./test_{count:03}.jpg'    #保存場所とファイル名
    with open(save_name, 'wb') as f:
        f.write(img_file.content)
    sleep(1)
    count+=1

ここのサイトのソースが簡単な構造になっているというのもあり、比較的楽に画像スクレイピングが出来ました。
最初はファイルのダウンロードが上手くいかなったのですが、調べたらRequestsを使えば出来ることが分かった。
色々使えるライブラリですね。

Beautifulsoupでスクレイピング

BeautifulsoupはHTMLタグを解析して取得してくれるライブラリです。
Pythonから使ってスクレイピングをしたいと思います。
HTTPライブラリのRequestsもインストールしておきます。

インストール

pip install beautifulsoup4
pip install requests

使い方

準備

RequestsでURLレスポンスを取得し、それを使ってBeautifulSoupオブジェクトを作成します。

import requests
from bs4 import BeautifulSoup

url='http://example.com'
res = requests.get(url)
soup = BeautifulSoup(res.text, 'html.parser')

タグ取得

  • ページ内のAタグの先頭のものだけ取得
feed = soup.find('a')
  • 全てのAタグを取得
feeds = soup.find_all('a')
  • 条件を指定して取得
feeds = soup.find_all('a', class_='sample')

Pythonでは「class」は予約後のため、「class_」になるので注意

タグの情報

  • Aタグのhrefを取得
feed = soup.find('a')
print(feed['href'])

または

feed = soup.find('a')
print(feed.get('href'))
  • Aタグで囲まれたテキストを取得
feed = soup.find('a')
print(feed.text)

スクレイピングしてみる

今回はヤフーニュースのトピックのタイトルとリンクの取得を目的とします。 https://news.yahoo.co.jp/topics/top-picks f:id:chaz4:20200202135704j:plain

HTMLソースを解析

ソースを開き、タイトルから追っていくと、liタグのnewsFeed_item_titleクラスが見つかります。
ここの親階層を辿っていくと、newsFeed_itemクラスが1つのニュースのまとまりだと思われます。

全ニュースを取得

全てのnewsFeed_itemクラスを取得

url = 'https://news.yahoo.co.jp/topics/top-picks'
req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')
feeds = soup.find_all('li', class_='newsFeed_item')

タイトルを取得

ループで一つずつ必要な情報を抜き出していきます。

for feed in feeds:
    title = feed.find(class_='newsFeed_item_title')
    if title:
        print(title.text)

1つのニュースの中で、さらにfindを使って今度はnewsFeed_item_titleクラスを探しています。
見つからなかった場合はNoneが返ってくるので判定しながら次に進みます。
textで文字を取得できます。
ここではタイトルのみを抜き出して表示しています。

リンクを取得

Aタグから取得したいところですが、このページではAタグで取得すると範囲が長いため、ゴチャゴチャした長い文字列になってしまいます。
そこで、普通の文字列で取得したいと思います。

正規表現を使いたいのでインポート。

import re

for feed in feeds:
    link = re.search(r'https://news.yahoo.co.jp/pickup/\d+', str(feed))
    if link:
        print(link.group())

文字列として、「https://news.yahoo.co.jp/pickup/数字」を検索しました。
検索で見つかった場合は、groupメソッドに入っています。

まとめ

今までのコードをまとめ、タイトルとリンクをセットで表示します。

import requests
import re
from bs4 import BeautifulSoup

url = 'https://news.yahoo.co.jp/topics/top-picks'
req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')
feeds = soup.find_all('li', class_='newsFeed_item')

for feed in feeds:
    title = feed.find(class_='newsFeed_item_title')
    link = re.search(r'https://news.yahoo.co.jp/pickup/\d+', str(feed))
    if title and link:
        print(title.text,link.group())

これを加工して色々応用出来ると思います。
次回は画像のスクレイピング&ダウンロードをやってみたいと思います。

Bashで画像ダウンロード

スクレイピングして画像をゲット

適当に選んだサイトから画像をダウンロードしてみたいと思います。

【最新】乃木坂46 衛藤美彩の水着グラビア画像集【みさみさ、みさ先輩】 - NAVER まとめ

水着画像ですが、たまたまこのサイトになっただけです。

ソースから画像の場所を探す

このサイトのソースを見て、画像にリンクされている箇所を探します。

どれでもいいので画像のサムネイルをクリックすると元の大きい画像が出てきて、さらにその画像をクリックするとURLが出ると思います。
色々な所からリンクされていたりするので全部がこの方法ではいかないかもしれないが。

とにかく元画像(JPGファイル)のURLを見つけたらサイトのソースでそれを検索。
複数出るけど、Aタグで囲まれている箇所を特定。
そしてAタグを囲んでいるclassを見つける。
というわけで、「mdMTMWidget01ItemCite01Value」でした。
このクラス名がある行からURLを抜き出していきます。


ソースの取得と抽出

wgetでファイルを取得していきます。
O(大文字のオー)のオプションで出力先を標準出力にすると、ソースコードが出力されます。
パイプラインで繋げてgrepを使い、ここから先ほどのクラス名の行を抽出する。

wget https://matome.naver.jp/odai/2149130246521074801 -O- | grep 'class="mdMTMWidget01ItemCite01Value"'

これで必要な行のみを抽出できました。
ここからさらに画像URLを絞り込んでいきます。
先ほどのコマンドにさらにパイプラインで繋げます。

grep -oP 'http.*.jpg'

正規表現を使ってhttpから続くjpgファイルのURLだけを抜き出しました。

ファイルをひとつずつダウンロードしていく

先ほどのコマンドを変数に入れ、その画像URLをひとつずつ配列に入れて、それを繰り返し処理していきます。
wgetのPオプションで保存先を指定。
サーバーの負担を減らすためにsleepで遅延しておきます。

#!/bin/bash

SRC=https://matome.naver.jp/odai/2149130246521074801

declare -a imgs=()

imgs=$(wget $SRC -O- | grep 'class="mdMTMWidget01ItemCite01Value"' | grep -oP 'http.*.jpg')
for file in ${imgs[@]}; do
    wget $file -P ~/Downloads/img
    sleep 1
done

これでとりあえず完成。
wgetの保存先は好きな場所に変えましょう。
=の前後はスペースを空けるとエラーになります。
上記をtest.sh等の名前で保存。

chmod +x test.sh

で実行権を付け、

./test.sh

で実行します。
これでどんどん画像がダウンロードされてきました。


Udemy売れ筋「実践 Python データサイエンス」

次のページも欲しい

サイトには複数ページがあるので、出来れば全てDLしたいのが人情です。
2ページ目へ行くと分かりますが、URLに?page=2というのが付くだけなので、URLをそれに直せばいいだけ。

しかし手動で全部やるのは面倒!
というわけで、自動でやる手がかりを。

総ページ数さえ取得出来れば後はpageを変えながら同じことをするだけ。
このサイトですが、「MdPagination03」というクラスの所に全ページが集まっているようです。
よって、

wget $SRC | grep -B 1 '/MdPagination03' | grep -v '/MdPagination03' | perl -pe 's/.*>(\d+)<\/a>.*/$1/'

で最終ページを取得することができました。
何かスマートにいかず冗長になってしまった。
SRCは先ほど入れておいたやつ。
後はこれを使って、1から最終ページまで繰り返せば良いだけです。

まぁ、目視で最終ページを入力した方が早いかも(笑)


気になる本 1808

なれる!SE

SEを題材にしたラノベ

新人SEが奮闘する物語。
作者の方が元SEということで、SEの仕事に関してはかなり詳しい描写がされていて、それだけでも興味深い。
SEというのはいろんな仕事をするブラックな業界なんだと思った。
難しい用語が出てきたりするけど、簡単な説明があるので分かりやすい。ネットワーク系の仕事が多い感じ。

内容の方は、次々に登場する女子たちとのハプニングがあったり、協力したり、ラブコメ的な展開があったりという、どっちかというとハーレム系ラノベ的だと思います。
主人公がIT系の知識がないまま、こんな会社に入社しているのはどうかと思うが・・・。
巻が進むごとにマネージャーやったり、大口取引をしたりと成長している姿も見ることが出来ます。
最後の方のオチはなかなか面白かった。


会計天国

先の展開が気になる会計ストーリー

会計について解説する本ということで堅苦しい内容なのかと思いきや。
冒頭でいきなり事故死した主人公が天使に連れられて人助けをしにいくという漫画チックな展開で始まるため、入りやすい導入部。
普通の読み物として楽しめ、先の展開が気になってきます。

会計のノウハウを披露して登場する相手を導くというのがメインとなり、会計についての解説が図を交えて分かりやすく説明されていきます。
でも私はよく理解出来ませんでした・・・。
最後は主人公の娘に対する思いによりどんでん返しな展開になって終わるのもまた良いです。


投資ミサイル

笑いと感動の投資ストーリー

事業計画作成等について解説する本のようだが、これも「会計天国」と同じく堅苦しくはない。
新規事業を任されることになった女性課長の物語で、いきなりロボットの上司が登場するということで軽い感じで読み進められる。
ロボットは投資等についても分かりやすく解説してくれて、多少は勉強になります。私も株をやってみようかなと思ってしまった。
ツッコミどころ満載のロボットの行動、事業も自身も成長していく主人公の考え方の変化、ダメな彼氏とのやりとり等、先の展開が気になるストーリー。
最後は悲しい展開になりつつも良い終わり方だと思います。


気になるマンガ 1803

最近読んで気になったマンガの感想を簡単に書き留めておきます。
Kindleで1巻が無料だったから読み始めたとか、Kindle Unlimitedで読んだとかです。
全部の巻を読んだわけではありません。

かくしごと

サッパリとした絵とテンポが良いギャグ

漫画家をしているということを娘にバレないように日々を過ごすパパのお話。
個性的なキャラたちと、小気味良いセリフの応酬でテンポ良く進むし、ギャグもクスッときて面白い。
漫画家の実体験をネタにしてるようで自虐的に笑わせてくれます。
親バカで極端な行動をする主人公ですが、読んでる自分も姫ちゃんが可愛く思えます。
カラーページで別枠で展開されている数年後のストーリーも続きが気になります。

ハンツートラッシュ

エロいスポーツもの

水球というマイナースポーツを題材としたものだが、とにかくエロい描写が多い。
主人公もエロい目的で入部するというストレートな内容。
最初の方は水球の説明や試合が出てきたりして一応はスポーツものしてたのだが。
主人公をとりまく恋愛(?)展開のエピソードやラッキースケベ的なアクシデントばかりで、単なるエロマンガになったような。
でも先の展開は少し気になります。

霊能者と事故物件視てきました

物件リポートもので興味深い

格安の事故物件のリポートを4コママンガ形式で描いている。
霊能者が説明する、その建物に居る霊の過去や現況が少し怖かった。
立地や部屋割り等が変わったものが多いのが興味深く、他にもそこにまつわるエピソードがあったりして、変わった物件を知ることができます。