Pythonでウェブスクレイピング – BeautifulSoup ②

では前回練習したウェブスクレイピングの続きを説明します。

前回の記事はこちらからどうぞ。

今日はヤフオクに表示されている入札価格と商品名などをスクレイピングしていきたいと思います。

requestsのライブラリをインストール

ではPythonから実際のウェブサイトにアクセスするにあたりHTTPリクエストを送ることになります。その際にRequestsのライブラリを使うのでインストールしましょう。

前回、virtualenvで環境を作った人はアクティベートすることを忘れずに!

pip install requests

#最後のsを忘れずに!リクエスツです。

ではページのHTMLをスクレイピングします。

import requests

#URLに対象となるURLを入力
html_text = requests.get('https://auctions.yahoo.co.jp/category/list/26318/?p=%E8%87%AA%E5%8B%95%E8%BB%8A%E3%80%81%E3%82%AA%E3%83%BC%E3%83%88%E3%83%90%E3%82%A4&auccat=26318&fixed=2&exflg=1&b=1&n=50&s1=featured&o1=d&nockie=1').text
print(html_text)

ウェブページの内容が出てきました。

リスティングのHTMLを見る

ではデベロッパーツールで各リストを囲っているカードのエレメントをみます。

見てわかるようにliエレメントでProductというクラスがありますね。

ではこのProductクラスをすべてスクレイピングします。

from bs4 import BeautifulSoup
import requests

#URLに対象となるURLを入力
html_text = requests.get('https://auctions.yahoo.co.jp/category/list/26318/?p=%E8%87%AA%E5%8B%95%E8%BB%8A%E3%80%81%E3%82%AA%E3%83%BC%E3%83%88%E3%83%90%E3%82%A4&auccat=26318&fixed=2&exflg=1&b=1&n=50&s1=featured&o1=d&nockie=1').text

soup = BeautifulSoup(html_text, 'lxml')
listings = soup.find_all('li', class_='Product')
print(listings)

Pythonファイルを実行してちゃんとスクレイピングできているか確かめましょう。

次に一つのリスティングから必要な情報を吸い取ります。

from bs4 import BeautifulSoup
import requests

#URLに対象となるURLを入力
html_text = requests.get('https://auctions.yahoo.co.jp/category/list/26318/?p=%E8%87%AA%E5%8B%95%E8%BB%8A%E3%80%81%E3%82%AA%E3%83%BC%E3%83%88%E3%83%90%E3%82%A4&auccat=26318&fixed=2&exflg=1&b=1&n=50&s1=featured&o1=d&nockie=1').text

soup = BeautifulSoup(html_text, 'lxml')
listing = soup.find('li', class_='Product')
listing_title = listing.find('a', class_='Product__titleLink').text
listing_price = listing.find('span', class_='Product__priceValue').text
time_left = listing.find('span', class_='Product__time').text
print(listing_title)
print(listing_price)
print(time_left)

ではこのリスティングをループさせます。

from bs4 import BeautifulSoup
import requests

#URLに対象となるURLを入力
html_text = requests.get('https://auctions.yahoo.co.jp/category/list/26318/?p=%E8%87%AA%E5%8B%95%E8%BB%8A%E3%80%81%E3%82%AA%E3%83%BC%E3%83%88%E3%83%90%E3%82%A4&auccat=26318&fixed=2&exflg=1&b=1&n=50&s1=featured&o1=d&nockie=1').text

soup = BeautifulSoup(html_text, 'lxml')
listings = soup.find_all('li', class_='Product')

for listing in listings:
    listing_title = listing.find('a', class_='Product__titleLink').text
    listing_price = listing.find('span', class_='Product__priceValue').text
    time_left = listing.find('span', class_='Product__time').text
    print(listing_title)
    print(listing_price)
    print(time_left)
    print('---------')

10分ごとにスクレイピングを実行させる

では先ほどのコードをファンクションにして10分ごとに実行させるように設定します。

from bs4 import BeautifulSoup
import requests
import time
#URLに対象となるURLを入力
html_text = requests.get('https://auctions.yahoo.co.jp/category/list/26318/?p=%E8%87%AA%E5%8B%95%E8%BB%8A%E3%80%81%E3%82%AA%E3%83%BC%E3%83%88%E3%83%90%E3%82%A4&auccat=26318&fixed=2&exflg=1&b=1&n=50&s1=featured&o1=d&nockie=1').text

soup = BeautifulSoup(html_text, 'lxml')
listings = soup.find_all('li', class_='Product')

def find_listings():
    for listing in listings:
        listing_title = listing.find('a', class_='Product__titleLink').text
        listing_price = listing.find('span', class_='Product__priceValue').text
        time_left = listing.find('span', class_='Product__time').text
        print(listing_title)
        print(listing_price)
        print(time_left)
        print('---------')

if __name__ == '__main__':
    while True:
        find_listings()
        # minutes to wait
        time_wait = 10
        print(f'Waiting {time_wait} minute(s)' )
        time.sleep(time_wait * 60)

データをSCVに書き出す

日本語のエンコードは私は”utf_8_sig”で行いました。(アメリカのPCなので。。。

色々試してください。

from bs4 import BeautifulSoup
import requests
from csv import writer

#URLに対象となるURLを入力
url = 'https://auctions.yahoo.co.jp/category/list/26318/?p=%E8%87%AA%E5%8B%95%E8%BB%8A%E3%80%81%E3%82%AA%E3%83%BC%E3%83%88%E3%83%90%E3%82%A4&auccat=26318&fixed=2&exflg=1&b=1&n=50&s1=featured&o1=d&nockie=1'
html_text = requests.get(url).text

soup = BeautifulSoup(html_text, 'lxml')
listings = soup.find_all('li', class_='Product')

with open('listings.csv', 'w', encoding='utf_8_sig', newline='') as f:
    thewriter = writer(f)
    header = ['Title', 'Price', 'Time Left']
    thewriter.writerow(header)

    for listing in listings:
        listing_title = listing.find('a', class_='Product__titleLink').text
        listing_price = listing.find('span', class_='Product__priceValue').text
        time_left = listing.find('span', class_='Product__time').text
        info = [listing_title, listing_price, time_left]
        thewriter.writerow(info)