技術雑記帳兼日記帳

AWS、Python、Terraformの使い方をコッソリ

python スクレイピング その3

はじめに

今回はYahoo画像検索で猫の画像をかき集めて保存するプログラムを書いてみた。

準備

  • imageDownload.py
import requests, os, json, traceback
from bs4 import BeautifulSoup

path =  './img-cat/'
maxPage = 2
searchText = '猫'

def imageDownload(searchWord, index):
    url = 'https://search.yahoo.co.jp/image/search?p={searchWord}&ei=UTF-8&b={index}'
    resp = requests.get(url.format(searchWord=searchWord, index=index))
    soup = BeautifulSoup(resp.content, 'html.parser')

    #分析
    script = soup.find("script", attrs={"id": "__NEXT_DATA__"})

     # タグの内容を取り出してJSON変換
     # <script>なので中身はstringで取るみたい。
    scriptJson = json.loads(script.string)
    imageUrlList = []
    for algos in scriptJson['props']['initialProps']['pageProps']['algos']:
        imageUrlList.append(algos['main']['url'])

    #画像取得
    imageObjectList = []
    for imageUrl in imageUrlList:
        resp = requests.get(imageUrl)
        imageObjectList.append(resp.content)
    
    #画像リスト返却
    return imageObjectList

def imageWrite(imageList):
    for i, image in enumerate(imageList):
        fileName = path + 'img' + '{:04}'.format(i+1) + '.jpg'
        with open(fileName, 'wb') as saveImage:
            saveImage.write(image)

    return

if __name__ == '__main__':

    try:
        if os.path.exists(path) != True:
            os.mkdir(path)

        imageList = []
        # Page * 20ループで画像取得
        for i in range(int(maxPage)):
            #画像収集
            index = (i * 20) + 1
            imageList.extend(imageDownload(searchText, index))

        #画像書き込み
        imageWrite(imageList)

    except Exception as e:
        print(e)
        print(traceback.format_exc())
  • 実行方法と結果
$ python imageDownload.py 
$ ls img-cat/
img0001.jpg  img0003.jpg  img0005.jpg  img0007.jpg  img0009.jpg  img0011.jpg  img0013.jpg
:
  • 簡単な解説

Yahoo画像検索が1ページに付き20枚画像が取れる。
それを前提に以下で20ずつindexを勧めて画像を取得してリストに追加している。
リストにリストを追加する処理はextend(appendでやって1敗)

        # Page * 20ループで画像取得
        for i in range(int(maxPage)):
            #画像収集
            index = (i * 20) + 1
            imageList.extend(imageDownload(searchText, index))

ここでリストを全部渡して、カレントの下のディレクトリにファイルに出力している。

        #画像書き込み
        imageWrite(imageList)
  • 関数の解説

以下の処理でリクエストを投げて、結果を受け取っている。
特筆すべきはscriptにJSONでURLなどを保持しているところ。

def imageDownload(searchWord, index):
    url = 'https://search.yahoo.co.jp/image/search?p={searchWord}&ei=UTF-8&b={index}'
    resp = requests.get(url.format(searchWord=searchWord, index=index))
    soup = BeautifulSoup(resp.content, 'html.parser')

    #分析
    script = soup.find("script", attrs={"id": "__NEXT_DATA__"})

あとは、JSONを分析+URLのリストを作って画像をダウンロードしてimageObjectListに保存している。

    scriptJson = json.loads(script.string)
    imageUrlList = []
    for algos in scriptJson['props']['initialProps']['pageProps']['algos']:
        imageUrlList.append(algos['main']['url'])

    #画像取得
    imageObjectList = []
    for imageUrl in imageUrlList:
        resp = requests.get(imageUrl)
        imageObjectList.append(resp.content)
    
    #画像リスト返却
    return imageObjectList

imageWriteはリストを吐き出しているだけなので省略


まとめ

スクレイピングをやっていると、どんどんこれやっていいのかってなってくるので方向性がぶれてくる。
だけど、やりたいことはできたので良しとする。