TekRog
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)

参考

・環境構築