Javaを使ったスクレイピング

今回はウェブサイトから株の情報を取得し CSVに出力する方法を紹介します。

1. 環境

Eclipse(Version: 2022-09 (4.25.0))

Java17



依存関係


	org.jsoup
	jsoup
	1.15.3



jsoupを使ってHTMLを解析するため上記をpom.xmlに追加する。

Mavenプロジェクトではない場合は下記サイトから Jarをダウンロードしてライブラリに追加する。


jarダウンロードサイト
https://jsoup.org/download

2. DTOクラスの作成


まず最初のHTML画面から取得した情報を 保存するためのDTOを作成する。

株の名称や、値段等の情報を保持する。

StockInformationDto.java

package com.example.demo.Dto;

public class StockInformationDto {

	//ファンド名称
	private String fundName;
	
	//基準価額(円)
	private String baseMarketValue;
	
	//前日比(円)
	private String previousDayRatio;
	
	//純資産(億円)
	private String netAsset;

	public String getFundName() {
		return fundName;
	}

	public void setFundName(String fundName) {
		this.fundName = fundName;
	}

	public String getBaseMarketValue() {
		return baseMarketValue;
	}

	public void setBaseMarketValue(String baseMarketValue) {
		this.baseMarketValue = baseMarketValue;
	}

	public String getPreviousDayRatio() {
		return previousDayRatio;
	}

	public void setPreviousDayRatio(String previousDayRatio) {
		this.previousDayRatio = previousDayRatio;
	}

	public String getNetAsset() {
		return netAsset;
	}

	public void setNetAsset(String netAsset) {
		this.netAsset = netAsset;
	}
}

3. スクレイピングクラスの作成


対象のURLからHTML形式の画面を取得し、 その中から必要な情報を抽出する。

今回は株価情報の乗っているサイトの情報を取得し ファンド名と、株価情報を取得しListに格納していく。

StockInformationAcquisition.java

package com.example.demo.Scraping;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.example.demo.Dto.StockInformationDto;

public class StockInformationAcquisition {

	//株価情報を取得する
	public List scraping() {
		
		//価格格納
		List priceList = new ArrayList();
		//株情報格納
		List stockList = new ArrayList();
		//情報格納用
		int cnt = 0;
		//HTMLDocument
		Document document;
		
		try {
			// 記載したURLにGETリクエストを送る
			document = Jsoup.connect("https://www.am.mufg.jp/smp/f_info/kagaku_list/").get();
		} catch (IOException e) {
			//例外時の処理
			e.printStackTrace();
			return stockList;
		}

		//IDで要素を取得
		//ファンド名
		Elements fund = document.select(".fund");
		//価格
		Elements price = document.select(".price");
		
		//価格情報の取り出し
		for (Element element : price) {
			//同じ配列複数の値がいるので分割する
			String[] str = element.text().split(" ");
			//基準価格、前日比、純資産それぞれを格納する
			for (int i = 0; i < str.length; i++) {
				priceList.add(str[i]);
			}
		}

		//取得した株情報をListに格納する
		for (Element element : fund) {
			StockInformationDto stockInfo = new StockInformationDto();

			//ファンド名記載
			stockInfo.setFundName(element.text());

			//1つのファンドに対して3つの価格情報があるので1回ごとに3データ読み取り記載
			stockInfo.setBaseMarketValue(priceList.get(3 * cnt));
			stockInfo.setPreviousDayRatio(priceList.get(3 * cnt + 1));
			stockInfo.setNetAsset(priceList.get(3 * cnt + 2));
			
			//List格納
			stockList.add(stockInfo);
			//何個目の価格情報か判断するため処理ごとにインクリメントする
			cnt++;
			
		}
		
		return stockList;

	}

}

4. CSV出力クラスの作成


 StockCsv.java

package com.example.demo.Csv;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import com.example.demo.Dto.StockInformationDto;

public class StockCsv {

	//CSVファイルの出力
	public void exportCsv(List stockList) {
		
		try {
			 // 出力ファイルの作成
			FileWriter fw = new FileWriter("stockInfo.csv", false);
	        // PrintWriterクラスのオブジェクトを生成
	        PrintWriter pw = new PrintWriter(new BufferedWriter(fw));
	        
	        //ヘッダー作成
	        pw.print("ファンド名称");
	        pw.print(",");
	        pw.print("基準価額(円)");
	        pw.print(",");
	        pw.print("前日比(円)");
	        pw.print(",");
	        pw.print("純資産(億円)");
	        pw.print(",");
	        pw.println();
	        
	        for (StockInformationDto stockInfo : stockList) {
	        	 // データを書き込む
	        	pw.print(stockInfo.getFundName());
		        pw.print(",");
		        pw.print(stockInfo.getBaseMarketValue().replace(",", ""));
		        pw.print(",");
		        pw.print(stockInfo.getPreviousDayRatio().replace(",", ""));
		        pw.print(",");
		        pw.print(stockInfo.getNetAsset().replace(",", ""));
		        pw.print(",");
		        pw.println();
			}
	        
	        // ファイルを閉じる
            pw.close();
	        
		} catch (IOException e) {
			//エラー時の処理
			e.printStackTrace();
		}

		
	}
	
}

上記のように1レコードずつCSV出力している。

1点注意点が価格情報の中に”,”が入っているのでCSV作成前に置換して消しておく。

5. メインクラスの作成

Main.java

package com.example.demo;

import java.util.List;

import com.example.demo.Csv.StockCsv;
import com.example.demo.Dto.StockInformationDto;
import com.example.demo.Scraping.StockInformationAcquisition;

public class Main {

	public static void main(String[] args) {
		
		//インスタンス作成
		StockInformationAcquisition stock = new StockInformationAcquisition();
		StockCsv stockCsv = new StockCsv();
		
		//スクレイピングにてデータ取得の処理
		List stockList = stock.scraping();
		
		//CSV出力の実施
		stockCsv.exportCsv(stockList);
		
		
	}

}

先ほど作成したクラスを呼び出しCSVファイルが作成される。

6. まとめ

意外と簡単にスクレイピングをすることができて驚いた。

JavaScriptなどの知識がもっとあればいろいろなデータ取得ができると思うので スクレイピングする際はそちらの知識もつけたいと思った。