thumbnail

Vue3+Laravel+Pythonでスクレイピング

Vue3、Laravel、Pythonを用いてWebスクレイピングを行う簡単なSPAを試作しました。その時の備忘録です。

構成

構成と説明

  1. ①VueからLaravelサーバにGETリクエスト
  2. ②LaravelがPythonを実行
  3. ③Pythonでスクレイピング
  4. ④LaravelがPythonの出力をJSONにしてVueへ返す
  5. ⑤Vueで結果を表示

なぜこの構成か?

  • 将来的にこの構成で機械学習のWebアプリを作りたい。そのためのテストを兼ねている。
  • サーバにPythonを用いてないのは、学習コストとLaravelの需要。
  • Vue、Laravel、Pythonそれぞれのスキルアップを図りたい。

作成するもの

作成するアプリの説明

このブログの任意の記事のURLを入力してサーバにリクエストすると、サブタイトルの一覧を返却するSPA。

表示画面とコード

画面表示

コード

要件を満たす最低限のコードのみ実装。
ディレクトリ階層も適当。

Vue3

出力はローディング画面と得られた結果のみ。
エラーハンドリングはなし。

script

<script lang="ts" setup>
import axios from 'axios';
import { ref } from 'vue';

const text = ref('https://xs363422.xsrv.jp/glLRkIDa6p/vue3-ts-quickmanual/')
const data = ref<string[]>()
const isLoading = ref(false)

const onclick = async () => {
  isLoading.value = true
  const response = await axios.get<string[]>(`http://localhost:8000/api/titles/?url=${text.value}`)
  isLoading.value = false
  data.value = response.data
}
</script>

temlate

<template>
  <h1>スクレイピング</h1>
  <p>
    <label>
      URL :
      <input type="text" v-model="text" :style="{width: '400px'}"/>
    </label>
  </p>
  <button @click="onclick">スクレイピング</button>
  <div>
    <p>出力</p>
    <div v-if="isLoading">Loading...</div>
    <div v-else>
      <ul>
        <li v-for="(h2, i) in data" key="i">{{ h2 }}</li>
      </ul>
    </div>
  </div>
</template>

Laravel

ルーティング:/routes/api.php

<?php

use Illuminate\Support\Facades\Route;
Route::get('/titles', 'App\Http\Controllers\ScrapingController@create');

コントローラ:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ScrapingController extends Controller
{
    public function index()
    {
        return view("index");
    }

    public function create(Request $request)
    {
        $url = $request->url;
        $command = "python3 scraping.py {$url}";
        exec($command, $outputs);
        return $outputs;
    }
}

Python

/publicに配置。
コントローラで実行するコマンドにおいて、
ファイルパスを指定しないと、このディレクトリのファイルを参照するため。

import sys
import requests
from bs4 import BeautifulSoup

args = sys.argv
url =  args[1]
res = requests.get(url)
soup = BeautifulSoup(res.text, 'html.parser')

for h2 in soup.select('.single-content > h2'):
  print(h2.text)

参考

・環境構築