見出し画像

python:WEBアプリを作ろう(djangoでスクレイピング)

今回は、pythonのWebフレームワークのdjangoを使って、YahooNewsのURLを入力すれば、そのURLに記載されているタイトルとURLを抽出し、違うページに簡単にタイトルとURLを表示するような無意味なWebアプリを作ってみましょう。

キャプチャ

キャプチャ

projectの作成

django-admin startproject newsproject .


アプリの作成

python3 manage.py startapp newsapp


templatesフォルダの作成

キャプチャ

※manage.pyが存在するフォルダに作成。後ほど、このフォルダにURLオブジェクトを作るためのページと情報を表示するためのページ。bootstapを使うためのhtmlを作成し、入れ込みます。


newsprojectのsetting.pyの編集

INSTALLED_APPS = [
   'django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',
   'newsapp', #追記
]

作ったアプリ名を追記します。

TEMPLATES = [
   {
       'BACKEND': 'django.template.backends.django.DjangoTemplates',
       'DIRS': [BASE_DIR, 'templates'], #追記
       'APP_DIRS': True,
       'OPTIONS': {
           'context_processors': [
               'django.template.context_processors.debug',
               'django.template.context_processors.request',
               'django.contrib.auth.context_processors.auth',
               'django.contrib.messages.context_processors.messages',
           ],
       },
   },
]

BASE_DIRは、manage.pyがあるフォルダを示し、その中のtemplatesフォルダをTEMPLATESとみなすような設定です。


newsprojectのurls.pyの編集

from django.contrib import admin
from django.urls import path, include#追記
urlpatterns = [
   path('admin/', admin.site.urls),
   path('', include('newsapp.urls')), #追記
]

localhost:8000にアクセスするとnewsapp.urlsを見に行くような設定です。


アプリフォルダにurls.pyを作成し、編集

from django.urls import path
from .views import Create, listfunc

urlpatterns = [
   path('', Create.as_view(), name='home'),
   path('list/', listfunc, name='list'),
]

localhost:8000にアクセスされた場合、Createクラスが実行され、localhost:8000/list/にアクセスすると listfuncが実行されるような設定です。

Createクラスとlistfuncは後で作成します。


アプリフォルダのviews.pyを編集

from django.shortcuts import render
from .models import News
from django.views.generic import CreateView
from django.urls import reverse_lazy
import urllib.request
import requests
from bs4 import BeautifulSoup


class Create(CreateView):
   template_name = 'home.html'
   model = News
   fields = ('url',)
   success_url = reverse_lazy('list')


def listfunc(request):
   for post in News.objects.all():
       url = post.url
   list = []
   response = requests.get(url)
   bs = BeautifulSoup(response.text, "html.parser")
   ul_tag = bs.find_all(class_="topicsList_main")
   for tag in ul_tag[0]:
      title = tag.a.getText()
      url2 = tag.a.get("href")
      list.append([title, url2])
   context = {'list': list,}
   return render(request, 'list.html', context)

Createクラスでフォームから受け取ったurlオブジェクトを作成し、lisufuncで

そのurlオブジェクトを使ってスクレイピングしています。もっと簡単な方法があると思いますが、今回は、上記のような感じで作成しました。

アプリフォルダのmodels.pyを編集

from django.db import models

class News(models.Model):
   url = models.CharField(max_length=100)


マイグレーションを行う

python3 manage.py makemigrations
python3 manage.py migrate



base.htmlを作成

<!doctype html>
<html lang="en">
 <head>
   <!-- Required meta tags -->
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
   <!-- Bootstrap CSS -->
   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
   <title>Pachi Data</title>
 </head>
 <body>
   {% block header %}
   {% endblock header %}
   {% block content %}
   {% endblock content %}
   <!-- Optional JavaScript -->
   <!-- jQuery first, then Popper.js, then Bootstrap JS -->
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
   <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
   <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
 </body>
</html>

※boostrapのStarterTemplateを貼り付け、bodyの中にblock headerとblock contentを追記しています。


home.htmlを作成

{% extends 'base.html' %}

{% block header %}
<div class="jumbotron">
   <div class="container">
     <h1 class="display-4">News</h1>
     <p class="lead">Enter the URL</p>
   </div>
 </div>
{% endblock header %}

{% block content %}
<div class="container">
<form action='' method='POST'>{% csrf_token %}
<p>URL: <input type="text" name='url'></p>
<input type="submit" value="取得する">
</form>
</div>
{% endblock content %}

URLオブジェクトを作成するためのトップページです。


list.htmlを作成

{% extends 'base.html' %}

{% block header %}
<div class="jumbotron">
   <div class="container">
     <h1 class="display-4">News</h1>
   </div>
 </div>
{% endblock header %}

{% block content %}
<div class="container">
<ul class="list-group list-group-flush">
 <table border="2">
   <tr>
     <th>タイトル</th>
     <th>URL</th>
   </tr>
   {% for post, post2 in list %} 
   <tr>
     <td>{{ post }}</td>
     <td><a href="{{ post2 }}">{{ post2 }}</a></td>
   </tr>
   {% endfor %}
 </table>
</ul>
</div>
{% endblock content %}

データを表示させるためのページです。


以上で完成となります。以下のコードでサーバーを起動して、確認してみてください。

python3 manage.py runserver


最終的な構成は以下のような感じです。

キャプチャ


過去記事


この記事が気に入ったらサポートをしてみませんか?