# biz clawler - ワークフロー説明書
###### tags: `こまーず`
## 前提
以下のような一覧ページと詳細ページで構成されるWebページを例に、
ワークフロー定義の方法を説明する。

※ 詳細ページ(右)
## ワークフロー定義の詳細
ワークフロー定義のため、以下2種類のjsonファイルを作成する。
|jsonファイル名|説明|備考|
|-|-|-|
|base.json|起点URLやクローリング間隔などを指定|1ワークフローにつき1ファイル|
|parse.json|起点URLからの巡回・抽出アクションを定義|1ワークフローにつきnファイル(上記例だと2ファイルで記述可能)|
### 参考:本ページにて定義するワークフローの動作イメージ

### base.json
起点URLとクエリパラメタ、クローリング時のコンフィグを設定する。
以下の例では、`1日間隔`で次の2ページを起点として巡回する。
- `http://hoge.com/?q="ラーメン 東京"`
- `http://hoge.com/?q="ラーメン 千葉"`
```json=
{
# オリジナル起点URL
"base_url":"http://hoge.com/",
# クエリ
"query":{
"q":[
"ラーメン 東京",
"ラーメン 千葉"
]
}
# クローリング間隔(以下は1日毎にクロールする)
"interval":{
"day": "1",
}
}
```
### parse.json
クローリングおよびスクレイピング方法を記述する。
#### 前提:jsonの構成
`parse.json`には、
keyは任意の名前、valueは以下の要素を持つdictを指定する。
|key|valueの型|説明|デフォルト値|必須|
|-|-|-|-|-|
|selector|str|cssセレクタ|None|○|
|type|str|ノードの処理方法を定義する。詳細は以下。|None|○|
|attribute|str|`type`が`attribute`ならば指定<br>どの属性を抽出するかを指定。|None|☓|
|multiple|boolean|`true時`: 複数ノードから情報を抽出する。|false|☓|
#### typeで指定できる値
|値|対応する処理|
|-|-|
|link|ノードから"href"の属性値(=URL)を抽出する。<br>抽出したURLは、親dictデータのkeyと対応する`parse.json`に渡される。|
|text|ノードから`<tag>`の内側のデータを抽出する。|
|attribute|ノードから属性値を抽出する。(属性名は親dictの`attribute`で指定する。)|
<補足>
`type`として、`text`か`attribute`を指定すると、
抽出した結果をスクレイピング結果として出力する。
`link`の場合、スクレイピング結果として出力はせず、クローリング処理においてのみ利用する。
### ユースケース:一覧ページに対する`parse.json`
```json=
# main.json
{
# selectorを用いてURLを取得。
# URLは`shousai_page.xml`で処理する。
"shousai_page":{
"selector":"BODY > ... > a.contents",
"type":"link",
"multiple": "true"
},
# `$next_page`のみ、再帰的に処理を行う。
# (selectorにより得られたURLは、同jsonファイルで処理される)。
"$next_page":{
"selector":"BODY > ... > a.next",
"type":"link",
},
}
```
### ユースケース:詳細ページに対する`parse.json`
```json=
# shousai_page.json
{
# 以下、全てデータ抽出処理
"shop":{
"selector":"BODY > ... > div.shop",
"type":"text",
},
"grade":{
"selector":"BODY > ... > div.grade",
"type":"text",
},
"desc":{
"selector":"BODY > ... > div.desc",
"type":"text",
},
"link":{
"selector":"BODY > ... > a.link",
"type":"attribute",
"attribute":"href",
},
# 以下は残課題
"comment":{
"body": {
"selector":"BODY > ... > p.comment-body",
"type":"attribute",
"attribute":"text",
},
"author": {
"selector":"BODY > ... > p.comment-author",
"type":"attribute",
"attribute":"text",
},
"multiple": "true"
}
```
#### 補足:ScrapyのItem生成について
`type`の値が`attribute`か`text`のdictデータを用いることで、 Item(=テーブル)を生成する。
(1つの`parse.json`ファイルから、原則1つのItemを生成する)
例えば、上記`shousai_page.json`からは`shop`, `grade`, `desc`, `link`の要素を持つItemが生成される。
上記`main.json`では、全てのdictデータの`type`が`attribute`のため
`main.json`からはItemが生成されない。
## 参考
- https://selectorlib.com/scrapy.html
## 1205
- 将来的な拡張性として、後処理方法追加する