DjangoとScrapyのデータベースを共有させる

# クローリングしたデータを、Djangoで作成したテーブルに登録し、データベースAPIで扱えるようにする

コード少なめで参照URLの列挙になります。

## 1. Djangoでデータベース、モデルを作成
https://docs.djangoproject.com/ja/3.0/intro/tutorial02/
このURLを参考に２章の"モデルの作成"まで進める。
数分で終わるから自分の目で勉強しよう。


blogs/models.py に

```python:models.py
class Racelist(models.Model):
    url = models.TextField(unique=True)
    title = models.TextField()
    place = models.TextField()
    date = models.DateTimeField()
```
を作成したとする。これにスクレイピングしたデータを詰め込んでいく。
チュートリアルにしたがって makemigrations してファイルの中身を確認

`$python manage.py sqlmigrate Posts 0001`

```
CREATE TABLE "blogs_racelist" (
	"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
	"url" text NOT NULL UNIQUE, 
	"title" text NOT NULL, 
	"place" text NOT NULL, 
	"date" datetime NOT NULL);
```

なお、これで作成されるテーブル名は blogs_racelist であることに注意。

## 2.Scrapyの方のテーブル定義
https://qiita.com/Chanmoro/items/f4df85eb73b18d902739
このリンクを参考にScrapyを実装
データベースは簡単にsqlite で構わない。
items.py に定義するクラス名を、djangoで作成したテーブル名 (例: Blogs_racelist) とする。

```python:items.py
import scrapy
class Blogs_racelist(scrapy.Item):
    url = scrapy.Field()
    title = scrapy.Field()
    place = scrapy.Field()
    date = scrapy.Field()
```

続いて scrapyのpipelineにおいて、
sqlite3.connect() のURLを、Djangoプロジェクトのdb.sqlite3へのパスにする。
デフォルトならdb.sqlite3ファイルが、Djangoが使用するデータベースであり、Scrapyで定義したテーブルがある場所
筆者の場合、以下のようなファイル構成にしたので、
sqlite3.connect('~~/keiba_project/myblog/db.sqlite3')) である。

```
.
├── README.md
└── myblog
    ├── accounts
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-36.pyc
    │   │   ├── __init__.cpython-37.pyc
    │   │   ├── admin.cpython-36.pyc
    │   │   ├── admin.cpython-37.pyc
    │   │   ├── apps.cpython-36.pyc
    │   │   ├── apps.cpython-37.pyc
    │   │   ├── models.cpython-36.pyc
    │   │   ├── models.cpython-37.pyc
    │   │   ├── urls.cpython-36.pyc
    │   │   ├── urls.cpython-37.pyc
    │   │   ├── views.cpython-36.pyc
    │   │   └── views.cpython-37.pyc
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   ├── __init__.py
    │   │   └── __pycache__
    │   │       ├── __init__.cpython-36.pyc
    │   │       └── __init__.cpython-37.pyc
    │   ├── models.py
    │   ├── templates
    │   │   └── accounts
    │   │       └── signup.html
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    ├── admin
    │   ├── css
    │   │   ├── autocomplete.css
    │   │   ├── base.css
    │   │   ├── changelists.css
    │   │   ├── dashboard.css
    │   │   ├── fonts.css
    │   │   ├── forms.css
    │   │   ├── login.css
    │   │   ├── responsive.css
    │   │   ├── responsive_rtl.css
    │   │   ├── rtl.css
    │   │   ├── vendor
    │   │   │   └── select2
    │   │   │       ├── LICENSE-SELECT2.md
    │   │   │       ├── select2.css
    │   │   │       └── select2.min.css
    │   │   └── widgets.css
    │   ├── fonts
    │   │   ├── LICENSE.txt
    │   │   ├── README.txt
    │   │   ├── Roboto-Bold-webfont.woff
    │   │   ├── Roboto-Light-webfont.woff
    │   │   └── Roboto-Regular-webfont.woff
    │   ├── img
    │   │   ├── LICENSE
    │   │   ├── README.txt
    │   │   ├── calendar-icons.svg
    │   │   ├── gis
    │   │   │   ├── move_vertex_off.svg
    │   │   │   └── move_vertex_on.svg
    │   │   ├── icon-addlink.svg
    │   │   ├── icon-alert.svg
    │   │   ├── icon-calendar.svg
    │   │   ├── icon-changelink.svg
    │   │   ├── icon-clock.svg
    │   │   ├── icon-deletelink.svg
    │   │   ├── icon-no.svg
    │   │   ├── icon-unknown-alt.svg
    │   │   ├── icon-unknown.svg
    │   │   ├── icon-viewlink.svg
    │   │   ├── icon-yes.svg
    │   │   ├── inline-delete.svg
    │   │   ├── search.svg
    │   │   ├── selector-icons.svg
    │   │   ├── sorting-icons.svg
    │   │   ├── tooltag-add.svg
    │   │   └── tooltag-arrowright.svg
    │   └── js
    │       ├── SelectBox.js
    │       ├── SelectFilter2.js
    │       ├── actions.js
    │       ├── actions.min.js
    │       ├── admin
    │       │   ├── DateTimeShortcuts.js
    │       │   └── RelatedObjectLookups.js
    │       ├── autocomplete.js
    │       ├── calendar.js
    │       ├── cancel.js
    │       ├── change_form.js
    │       ├── collapse.js
    │       ├── collapse.min.js
    │       ├── core.js
    │       ├── inlines.js
    │       ├── inlines.min.js
    │       ├── jquery.init.js
    │       ├── popup_response.js
    │       ├── prepopulate.js
    │       ├── prepopulate.min.js
    │       ├── prepopulate_init.js
    │       ├── timeparse.js
    │       ├── urlify.js
    │       └── vendor
    │           ├── jquery
    │           │   ├── LICENSE.txt
    │           │   ├── jquery.js
    │           │   └── jquery.min.js
    │           ├── select2
    │           │   ├── LICENSE.md
   
    │           │   ├── select2.full.js
    │           │   └── select2.full.min.js
    │           └── xregexp
    │               ├── LICENSE.txt
    │               ├── xregexp.js
    │               └── xregexp.min.js
    ├── blogs
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-36.pyc
    │   │   ├── __init__.cpython-37.pyc
    │   │   ├── admin.cpython-36.pyc
    │   │   ├── admin.cpython-37.pyc
    │   │   ├── apps.cpython-36.pyc
    │   │   ├── apps.cpython-37.pyc
    │   │   ├── models.cpython-36.pyc
    │   │   ├── models.cpython-37.pyc
    │   │   ├── urls.cpython-36.pyc
    │   │   ├── urls.cpython-37.pyc
    │   │   ├── views.cpython-36.pyc
    │   │   └── views.cpython-37.pyc
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   ├── 0001_initial.py
    │   │   ├── 0002_racelist.py
    │   │   ├── __init__.py
    │   │   └── __pycache__
    │   │       ├── 0001_initial.cpython-36.pyc
    │   │       ├── 0001_initial.cpython-37.pyc
    │   │       ├── 0002_racelist.cpython-37.pyc
    │   │       ├── __init__.cpython-36.pyc
    │   │       └── __init__.cpython-37.pyc
    │   ├── models.py
    │   ├── templates
    │   │   └── blogs
    │   │       ├── post_confirm_delete.html
    │   │       ├── post_detail.html
    │   │       ├── post_form.html
    │   │       └── post_list.html
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    ├── db.sqlite3 <- 標的
    ├── keiba_scrapy
    │   ├── scrapy.cfg
    │   └── ten_min_scrapy
    │       ├── __init__.py
    │       ├── __pycache__
    │       │   ├── __init__.cpython-37.pyc
    │       │   ├── items.cpython-37.pyc
    │       │   ├── pipelines.cpython-37.pyc
    │       │   └── settings.cpython-37.pyc
    │       ├── items.py
    │       ├── middlewares.py
    │       ├── pipelines.py <- 今いじっているファイル
    │       ├── settings.py
    │       └── spiders
    │           ├── __init__.py
    │           ├── __pycache__
    │           │   ├── __init__.cpython-37.pyc
    │           │   └── scrapy_blog_spider.cpython-37.pyc
    │           └── scrapy_blog_spider.py
    ├── manage.py
    ├── myblog
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-36.pyc
    │   │   ├── __init__.cpython-37.pyc
    │   │   ├── settings.cpython-36.pyc
    │   │   ├── settings.cpython-37.pyc
    │   │   ├── urls.cpython-36.pyc
    │   │   ├── urls.cpython-37.pyc
    │   │   ├── wsgi.cpython-36.pyc
    │   │   └── wsgi.cpython-37.pyc
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── static
    │   ├── css
    │   │   └── style.css
    │   └── data
    │       └── finalized_model.sav
    └── templates
        ├── 403.html
        ├── 404.html
        ├── base.html
        └── registration
            ├── logged_out.html
            └── login.html
```


同じくpipelineにおいて、テーブルに登録するようなメソッドに、Djangoで作成したテーブル名を使ってロジックを書いていく。

Spiderにおいてテーブル名を使うメソッドも、同一テーブル名に編集する必要がある。

初心者エンジニアがいちいち説明するより、方針を述べてあとはググってもらった方が、winwinだったりする。
全体の方針としては、

1. Djangoでテーブル作成　
2. Scrapyの接続先にDjangoのデータベースを登録
3. その中のtableを items, spider, pipeline が参照するようにする


疲れたら寝よう。デスクに向かって罵声を浴びせる前に。