yasuri 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +54 -24
- data/USAGE.ja.md +216 -72
- data/USAGE.md +225 -78
- data/exe/yasuri +5 -0
- data/lib/yasuri.rb +1 -0
- data/lib/yasuri/version.rb +1 -1
- data/lib/yasuri/yasuri.rb +71 -36
- data/lib/yasuri/yasuri_cli.rb +64 -0
- data/lib/yasuri/yasuri_links_node.rb +3 -3
- data/lib/yasuri/yasuri_map_node.rb +12 -27
- data/lib/yasuri/yasuri_node.rb +15 -37
- data/lib/yasuri/yasuri_paginate_node.rb +5 -4
- data/lib/yasuri/yasuri_struct_node.rb +5 -1
- data/lib/yasuri/yasuri_text_node.rb +5 -5
- data/spec/cli_resources/tree.json +8 -0
- data/spec/cli_resources/tree.yml +5 -0
- data/spec/cli_resources/tree_wrong.json +9 -0
- data/spec/cli_resources/tree_wrong.yml +6 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/yasuri_cli_spec.rb +83 -0
- data/spec/yasuri_spec.rb +125 -140
- data/yasuri.gemspec +3 -1
- metadata +31 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd5fc7327c6d09b37771ac1c3ec40db2c052bf49ec9a1627e9ae49e047102856
|
4
|
+
data.tar.gz: a645f1e09ce72b73c54e2055af6fbf81bb145c8823e1d8428bb19c042bbb661d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 654bd6cfe8012811283b1aa03e0dcc1200ce957ef4641eed2b5fa65956fb974070157b832e42f340d7299031756848c5118a7f43019ff94f088c49974e2304e8
|
7
|
+
data.tar.gz: 5ad07b82672ea2ceebfb8154bb91631c095e9ad8d69f3d62c0bf8d528c4c539fab2597f4112b4212bffe7ad641b30d913686e8e2bfea7dfdbdd9a4468311b6c0
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
[](https://github.com/tac0x2a/yasuri/actions/workflows/ruby.yml)
|
3
3
|
[](https://coveralls.io/r/tac0x2a/yasuri?branch=master) [](https://codeclimate.com/github/tac0x2a/yasuri/maintainability)
|
4
4
|
|
5
|
-
Yasuri (鑢) is an easy web-scraping library for supporting "[Mechanize](https://github.com/sparklemotion/mechanize)".
|
5
|
+
Yasuri (鑢) is an easy web-scraping library for supporting "[Mechanize](https://github.com/sparklemotion/mechanize)", and CLI tool using it.
|
6
6
|
|
7
7
|
Yasuri can reduce frequently processes in Scraping.
|
8
8
|
|
@@ -33,10 +33,10 @@ or
|
|
33
33
|
|
34
34
|
```ruby
|
35
35
|
# for Ruby 1.9.3 or lower
|
36
|
-
gem 'yasuri', '~>
|
36
|
+
gem 'yasuri', '~> 2.0', '>= 2.0.13'
|
37
37
|
|
38
38
|
# for Ruby 3.0.0 or lower
|
39
|
-
gem 'yasuri', '~> 3.
|
39
|
+
gem 'yasuri', '~> 3.1'
|
40
40
|
```
|
41
41
|
|
42
42
|
|
@@ -49,6 +49,7 @@ Or install it yourself as:
|
|
49
49
|
$ gem install yasuri
|
50
50
|
|
51
51
|
## Usage
|
52
|
+
### Use as library
|
52
53
|
|
53
54
|
```ruby
|
54
55
|
# Node tree constructing by DSL
|
@@ -60,40 +61,64 @@ root = Yasuri.links_root '//*[@id="menu"]/ul/li/a' do
|
|
60
61
|
|
61
62
|
# Node tree constructing by YAML
|
62
63
|
src = <<-EOYAML
|
63
|
-
|
64
|
-
node: links
|
64
|
+
links_root:
|
65
65
|
path: "//*[@id='menu']/ul/li/a"
|
66
|
-
|
67
|
-
|
68
|
-
- content: { node: text, path: "//*[@id='contents']/p[1]" }
|
66
|
+
text_title: "//*[@id='contents']/h2"
|
67
|
+
text_content: "//*[@id='contents']/p[1]"
|
69
68
|
EOYAML
|
70
69
|
root = Yasuri.yaml2tree(src)
|
71
70
|
|
72
71
|
|
73
72
|
# Node tree constructing by JSON
|
74
73
|
src = <<-EOJSON
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
},
|
83
|
-
{ "node" : "text",
|
84
|
-
"name" : "content",
|
85
|
-
"path" : "//*[@id='contents']/p[1]"
|
86
|
-
}
|
87
|
-
]
|
88
|
-
}
|
74
|
+
{
|
75
|
+
"links_root": {
|
76
|
+
"path": "//*[@id='menu']/ul/li/a",
|
77
|
+
"text_title": "//*[@id='contents']/h2",
|
78
|
+
"text_content": "//*[@id='contents']/p[1]"
|
79
|
+
}
|
80
|
+
}
|
89
81
|
EOJSON
|
90
82
|
root = Yasuri.json2tree(src)
|
91
83
|
|
84
|
+
|
85
|
+
# Execution and getting scraped result
|
92
86
|
agent = Mechanize.new
|
93
|
-
root_page = agent.get("http://some.scraping.page.net/")
|
87
|
+
root_page = agent.get("http://some.scraping.page.tac42.net/")
|
94
88
|
|
95
89
|
result = root.inject(agent, root_page)
|
96
|
-
# => [
|
90
|
+
# => [
|
91
|
+
# {"title" => "PageTitle 01", "content" => "Page Contents 01" },
|
92
|
+
# {"title" => "PageTitle 02", "content" => "Page Contents 02" },
|
93
|
+
# ...
|
94
|
+
# {"title" => "PageTitle N", "content" => "Page Contents N" }
|
95
|
+
# ]
|
96
|
+
```
|
97
|
+
|
98
|
+
### Use as CLI
|
99
|
+
|
100
|
+
```sh
|
101
|
+
# After gem installation..
|
102
|
+
$ yasuri help scrape
|
103
|
+
Usage:
|
104
|
+
yasuri scrape <URI> [[--file <TREE_FILE>] or [--json <JSON>]]
|
105
|
+
|
106
|
+
Options:
|
107
|
+
f, [--file=FILE] # path to file that written yasuri tree as json or yaml
|
108
|
+
j, [--json=JSON] # yasuri tree format json string
|
109
|
+
|
110
|
+
Getting from <URI> and scrape it. with <JSON> or json/yml from <TREE_FILE>. They should be Yasuri's format json or yaml string.
|
111
|
+
```
|
112
|
+
|
113
|
+
Example
|
114
|
+
```sh
|
115
|
+
$ yasuri scrape "https://www.ruby-lang.org/en/" -j '
|
116
|
+
{
|
117
|
+
"text_title": "/html/head/title",
|
118
|
+
"text_desc": "//*[@id=\"intro\"]/p"
|
119
|
+
}'
|
120
|
+
|
121
|
+
{"title":"Ruby Programming Language","desc":"\n A dynamic, open source programming language with a focus on\n simplicity and productivity. It has an elegant syntax that is\n natural to read and easy to write.\n "}
|
97
122
|
```
|
98
123
|
|
99
124
|
## Dev
|
@@ -108,6 +133,11 @@ $ rake
|
|
108
133
|
$ rspec spec/*spec.rb
|
109
134
|
```
|
110
135
|
|
136
|
+
### Test gem in local
|
137
|
+
```sh
|
138
|
+
$ gem build yasuri.gemspec
|
139
|
+
$ gem install yasuri-*.gem
|
140
|
+
```
|
111
141
|
### Release RubyGems
|
112
142
|
```sh
|
113
143
|
# Only first time
|
data/USAGE.ja.md
CHANGED
@@ -1,24 +1,31 @@
|
|
1
|
-
# Yasuri
|
1
|
+
# Yasuri
|
2
2
|
|
3
3
|
## Yasuri とは
|
4
|
-
Yasuri (鑢)
|
4
|
+
Yasuri (鑢) はWebスクレイピングを宣言的に行うためのライブラリと、それを用いたスクレイピングのコマンドラインツールです。
|
5
|
+
簡単な宣言的記法で期待結果を記述するだけで、"[Mechanize](https://github.com/sparklemotion/mechanize)" によるスクレイピングを実行します。
|
5
6
|
|
6
7
|
Yasuriは、スクレイピングにおける、よくある処理を簡単に記述することができます.
|
7
|
-
|
8
|
+
例えば、以下のような処理を簡単に実現することができます.
|
8
9
|
|
9
|
-
+ ページ内の複数のリンクを開いて、各ページをスクレイピングした結果をHashで取得する
|
10
10
|
+ ページ内の複数のテキストをスクレイピングし、名前をつけてHashにする
|
11
|
+
+ ページ内の複数のリンクを開いて、各ページをスクレイピングした結果をHashで取得する
|
11
12
|
+ ページ内に繰り返し出現するテーブルをそれぞれスクレイピングして、配列として取得する
|
12
|
-
+
|
13
|
-
|
14
|
-
これらを簡単に実装することができます.
|
13
|
+
+ ページネーションで提供される各ページのうち、最初の3ページだけをスクレイピングする
|
15
14
|
|
16
15
|
## クイックスタート
|
17
16
|
|
17
|
+
#### インストール
|
18
|
+
```sh
|
19
|
+
# for Ruby 2.3.2
|
20
|
+
$ gem 'yasuri', '~> 2.0', '>= 2.0.13'
|
18
21
|
```
|
22
|
+
または
|
23
|
+
```sh
|
24
|
+
# for Ruby 3.0.0 or upper
|
19
25
|
$ gem install yasuri
|
20
26
|
```
|
21
27
|
|
28
|
+
#### ライブラリとして使う
|
22
29
|
```ruby
|
23
30
|
require 'yasuri'
|
24
31
|
require 'machinize'
|
@@ -30,88 +37,59 @@ root = Yasuri.links_root '//*[@id="menu"]/ul/li/a' do
|
|
30
37
|
end
|
31
38
|
|
32
39
|
agent = Mechanize.new
|
33
|
-
root_page = agent.get("http://some.scraping.page.net/")
|
40
|
+
root_page = agent.get("http://some.scraping.page.tac42.net/")
|
34
41
|
|
35
42
|
result = root.inject(agent, root_page)
|
36
|
-
# => [
|
37
|
-
# {"title" => "
|
38
|
-
|
43
|
+
# => [
|
44
|
+
# {"title" => "PageTitle 01", "content" => "Page Contents 01" },
|
45
|
+
# {"title" => "PageTitle 02", "content" => "Page Contents 02" },
|
46
|
+
# ...
|
47
|
+
# {"title" => "PageTitle N", "content" => "Page Contents N" }
|
48
|
+
# ]
|
39
49
|
```
|
50
|
+
|
40
51
|
この例では、 LinkNode(`links_root`)の xpath で指定された各リンク先のページから、TextNode(`text_title`,`text_content`) の xpath で指定された2つのテキストをスクレイピングする例です.
|
41
52
|
|
42
53
|
(言い換えると、`//*[@id="menu"]/ul/li/a` で示される各リンクを開いて、`//*[@id="contents"]/h2` と `//*[@id="contents"]/p[1]` で指定されたテキストをスクレイピングします)
|
43
54
|
|
44
|
-
## 基本
|
45
|
-
|
46
|
-
1. パースツリーを作る
|
47
|
-
2. Mechanize の agent と対象のページを与えてパースを開始する
|
48
|
-
|
49
55
|
|
50
|
-
|
51
|
-
|
52
|
-
```ruby
|
53
|
-
require 'mechanize'
|
54
|
-
require 'yasuri'
|
56
|
+
#### CLIツールとして使う
|
57
|
+
上記と同じことを、CLIのコマンドとして実行できます。
|
55
58
|
|
59
|
+
```sh
|
60
|
+
$ yasuri scrape "http://some.scraping.page.tac42.net/" -j '
|
61
|
+
{
|
62
|
+
"links_root": {
|
63
|
+
"path": "//*[@id=\"menu\"]/ul/li/a",
|
64
|
+
"text_title": "//*[@id=\"contents\"]/h2",
|
65
|
+
"text_content": "//*[@id=\"contents\"]/p[1]"
|
66
|
+
}
|
67
|
+
}'
|
56
68
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
agent = Mechanize.new
|
64
|
-
page = agent.get(uri)
|
65
|
-
|
66
|
-
|
67
|
-
tree.inject(agent, page)
|
69
|
+
[
|
70
|
+
{"title":"PageTitle 01","content":"Page Contents 01"},
|
71
|
+
{"title":"PageTitle 02","content":"Page Contents 02"},
|
72
|
+
...,
|
73
|
+
{"title":"PageTitle N","content":"Page Contents N"}
|
74
|
+
]
|
68
75
|
```
|
69
76
|
|
70
|
-
|
71
|
-
以下は、jsonで上記と等価な解析ツリーを定義した例です.
|
77
|
+
結果はjson形式の文字列として取得できます。
|
72
78
|
|
73
|
-
|
74
|
-
|
75
|
-
src = <<-EOJSON
|
76
|
-
{ "node" : "links",
|
77
|
-
"name" : "title",
|
78
|
-
"path" : "/html/body/a",
|
79
|
-
"children" : [
|
80
|
-
{ "node" : "text",
|
81
|
-
"name" : "name",
|
82
|
-
"path" : "/html/body/p"
|
83
|
-
}
|
84
|
-
]
|
85
|
-
}
|
86
|
-
EOJSON
|
87
|
-
tree = Yasuri.json2tree(src)
|
88
|
-
```
|
79
|
+
----------------------------
|
80
|
+
## パースツリー
|
89
81
|
|
90
|
-
|
91
|
-
|
92
|
-
src = <<-EOYAML
|
93
|
-
title:
|
94
|
-
node: links
|
95
|
-
path: "/html/body/a"
|
96
|
-
children:
|
97
|
-
- name:
|
98
|
-
node: text
|
99
|
-
path: "/html/body/p"
|
100
|
-
EOYAML
|
101
|
-
tree = Yasuri.yaml2tree(src)
|
102
|
-
```
|
82
|
+
パースツリーとは、スクレイピングする要素と出力構造を宣言的に定義するための木構造データです。
|
83
|
+
パースツリーは入れ子になった Node で構成されます.Node は `Type`, `Name`, `Path`, `Childlen`, `Options` 属性を持っており、その `Type` に応じたスクレイピング処理を行います.(ただし、`MapNode` のみ `Path` を持ちません)
|
103
84
|
|
104
|
-
### Node
|
105
|
-
ツリーは入れ子になった *Node* で構成されます.
|
106
|
-
Node は `Type`, `Name`, `Path`, `Childlen`, `Options` を持っています.
|
107
|
-
(ただし、`MapNode` のみ `Path` を持ちません)
|
108
85
|
|
109
|
-
|
86
|
+
パースツリーは以下のフォーマットで定義されます.
|
110
87
|
|
111
88
|
```ruby
|
89
|
+
# 1ノードからなる単純なツリー
|
112
90
|
Yasuri.<Type>_<Name> <Path> [,<Options>]
|
113
91
|
|
114
|
-
#
|
92
|
+
# 入れ子になっているツリー
|
115
93
|
Yasuri.<Type>_<Name> <Path> [,<Options>] do
|
116
94
|
<Type>_<Name> <Path> [,<Options>] do
|
117
95
|
<Type>_<Name> <Path> [,<Options>]
|
@@ -120,12 +98,13 @@ Yasuri.<Type>_<Name> <Path> [,<Options>] do
|
|
120
98
|
end
|
121
99
|
```
|
122
100
|
|
123
|
-
|
101
|
+
**例**
|
124
102
|
|
125
103
|
```ruby
|
104
|
+
# 1ノードからなる単純なツリー
|
126
105
|
Yasuri.text_title '/html/head/title', truncate:/^[^,]+/
|
127
106
|
|
128
|
-
#
|
107
|
+
# 入れ子になっているツリー
|
129
108
|
Yasuri.links_root '//*[@id="menu"]/ul/li/a' do
|
130
109
|
struct_table './tr' do
|
131
110
|
text_title './td[1]'
|
@@ -135,6 +114,71 @@ end
|
|
135
114
|
```
|
136
115
|
|
137
116
|
|
117
|
+
パースツリーはRubyのDSL、JSON、YAMLのいずれかで定義することができます。
|
118
|
+
以下は、上記と同じパースツリーをそれぞれの記法で定義した例です。
|
119
|
+
|
120
|
+
**Ruby DSLで定義する場合**
|
121
|
+
```ruby
|
122
|
+
Yasuri.links_title '/html/body/a' do
|
123
|
+
text_name '/html/body/p'
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
**JSONで定義する場合**
|
128
|
+
```json
|
129
|
+
{
|
130
|
+
links_title": {
|
131
|
+
"path": "/html/body/a",
|
132
|
+
"text_name": "/html/body/p"
|
133
|
+
}
|
134
|
+
}
|
135
|
+
```
|
136
|
+
|
137
|
+
**YAMLで定義する場合**
|
138
|
+
```yaml
|
139
|
+
links_title:
|
140
|
+
path: "/html/body/a"
|
141
|
+
text_name: "/html/body/p"
|
142
|
+
```
|
143
|
+
|
144
|
+
**パースツリーの特殊なケース**
|
145
|
+
|
146
|
+
rootの直下の要素が1つだけの場合、Hash(Object)ではなく、その要素を直接返します。
|
147
|
+
```json
|
148
|
+
{
|
149
|
+
"text_title": "/html/head/title",
|
150
|
+
"text_body": "/html/body",
|
151
|
+
}
|
152
|
+
# => {"title": "Welcome to yasuri!", "body": "Yasuri is ..."}
|
153
|
+
|
154
|
+
{
|
155
|
+
"text_title": "/html/head/title"}
|
156
|
+
}
|
157
|
+
# => Welcome to yasuri!
|
158
|
+
```
|
159
|
+
|
160
|
+
|
161
|
+
jsonまたはyaml形式では、子Nodeを持たない場合、`path` を直接値に指定することができます。以下の2つのjsonは同じパースツリーになります。
|
162
|
+
|
163
|
+
```json
|
164
|
+
{
|
165
|
+
"text_name": "/html/body/p"
|
166
|
+
}
|
167
|
+
|
168
|
+
{
|
169
|
+
"text_name": {
|
170
|
+
"path": "/html/body/p"
|
171
|
+
}
|
172
|
+
}
|
173
|
+
```
|
174
|
+
|
175
|
+
|
176
|
+
--------------------------
|
177
|
+
## Node
|
178
|
+
|
179
|
+
Nodeはパースツリーの節または葉となる要素で、`Type`, `Name`, `Path`, `Childlen`, `Options` を持っており、その `Type` に応じてスクレイピングを行います.(ただし、`MapNode` のみ `Path` を持ちません)
|
180
|
+
|
181
|
+
|
138
182
|
#### Type
|
139
183
|
*Type* は Nodeの振る舞いを示します.Typeには以下のものがあります.
|
140
184
|
|
@@ -144,6 +188,8 @@ end
|
|
144
188
|
- *Paginate*
|
145
189
|
- *Map*
|
146
190
|
|
191
|
+
詳細は各ノードの説明を参照してください。
|
192
|
+
|
147
193
|
#### Name
|
148
194
|
*Name* は 解析結果のHashにおけるキーになります.
|
149
195
|
|
@@ -193,7 +239,8 @@ p1t.inject(agent, page) #=> "Hello"
|
|
193
239
|
p2u.inject(agent, page) #=> "HELLO,WORLD"
|
194
240
|
```
|
195
241
|
|
196
|
-
なお、同じページ内の複数の要素を一度にスクレイピングする場合は、`MapNode
|
242
|
+
なお、同じページ内の複数の要素を一度にスクレイピングする場合は、`MapNode`を使用します。詳細は、`MapNode`の例を参照してください。
|
243
|
+
|
197
244
|
|
198
245
|
### オプション
|
199
246
|
##### `truncate`
|
@@ -549,3 +596,100 @@ tree.inject(agent, page) #=> {
|
|
549
596
|
|
550
597
|
### オプション
|
551
598
|
なし
|
599
|
+
|
600
|
+
|
601
|
+
-------------------------
|
602
|
+
## 使い方
|
603
|
+
|
604
|
+
#### ライブラリとして使用する場合
|
605
|
+
ライブラリとして使用する場合は、DSL, json, yaml の形式でツリーを定義できます。
|
606
|
+
```ruby
|
607
|
+
require 'mechanize'
|
608
|
+
require 'yasuri'
|
609
|
+
|
610
|
+
|
611
|
+
# 1. パースツリーを作る
|
612
|
+
# DSLで定義する倍
|
613
|
+
tree = Yasuri.links_title '/html/body/a' do
|
614
|
+
text_name '/html/body/p'
|
615
|
+
end
|
616
|
+
|
617
|
+
# jsonで定義する場合
|
618
|
+
src = <<-EOJSON
|
619
|
+
{
|
620
|
+
links_title": {
|
621
|
+
"path": "/html/body/a",
|
622
|
+
"text_name": "/html/body/p"
|
623
|
+
}
|
624
|
+
}
|
625
|
+
EOJSON
|
626
|
+
tree = Yasuri.json2tree(src)
|
627
|
+
|
628
|
+
|
629
|
+
# yamlで定義する場合
|
630
|
+
src = <<-EOYAML
|
631
|
+
links_title:
|
632
|
+
path: "/html/body/a"
|
633
|
+
text_name: "/html/body/p"
|
634
|
+
EOYAML
|
635
|
+
tree = Yasuri.yaml2tree(src)
|
636
|
+
|
637
|
+
|
638
|
+
|
639
|
+
# 2. Mechanize の agent と対象のページを与えてパースを開始する
|
640
|
+
agent = Mechanize.new
|
641
|
+
page = agent.get(uri)
|
642
|
+
|
643
|
+
|
644
|
+
tree.inject(agent, page)
|
645
|
+
```
|
646
|
+
|
647
|
+
#### CLIツールとして使用する場合
|
648
|
+
|
649
|
+
**ヘルプ表示**
|
650
|
+
```sh
|
651
|
+
$ yasuri help scrape
|
652
|
+
Usage:
|
653
|
+
yasuri scrape <URI> [[--file <TREE_FILE>] or [--json <JSON>]]
|
654
|
+
|
655
|
+
Options:
|
656
|
+
f, [--file=FILE] # path to file that written yasuri tree as json or yaml
|
657
|
+
j, [--json=JSON] # yasuri tree format json string
|
658
|
+
|
659
|
+
Getting from <URI> and scrape it. with <JSON> or json/yml from <TREE_FILE>. They should be Yasuri's format json or yaml string.
|
660
|
+
```
|
661
|
+
|
662
|
+
CLIツールでは以下のどちらかの方法でパースツリーを指定します。
|
663
|
+
+ `--file`, `-f` オプションで、ファイルに出力されたjson形式またはyaml形式のパースツリーを読み込む
|
664
|
+
+ `--json`, `-j` オプションで、パースツリーを文字列として直接指定する
|
665
|
+
|
666
|
+
|
667
|
+
**パースツリーをファイルで指定する例**
|
668
|
+
```sh
|
669
|
+
% cat sample.yml
|
670
|
+
text_title: "/html/head/title"
|
671
|
+
text_desc: "//*[@id=\"intro\"]/p"
|
672
|
+
|
673
|
+
% yasuri scrape "https://www.ruby-lang.org/en/" --file sample.yml
|
674
|
+
{"title":"Ruby Programming Language","desc":"\n A dynamic, open source programming language with a focus on\n simplicity and productivity. It has an elegant syntax that is\n natural to read and easy to write.\n "}
|
675
|
+
|
676
|
+
% cat sample.json
|
677
|
+
{
|
678
|
+
"text_title": "/html/head/title",
|
679
|
+
"text_desc": "//*[@id=\"intro\"]/p"
|
680
|
+
}
|
681
|
+
|
682
|
+
% yasuri scrape "https://www.ruby-lang.org/en/" --file sample.json
|
683
|
+
{"title":"Ruby Programming Language","desc":"\n A dynamic, open source programming language with a focus on\n simplicity and productivity. It has an elegant syntax that is\n natural to read and easy to write.\n "}
|
684
|
+
```
|
685
|
+
|
686
|
+
**パースツリーをjsonで直接指定する例**
|
687
|
+
```sh
|
688
|
+
$ yasuri scrape "https://www.ruby-lang.org/en/" -j '
|
689
|
+
{
|
690
|
+
"text_title": "/html/head/title",
|
691
|
+
"text_desc": "//*[@id=\"intro\"]/p"
|
692
|
+
}'
|
693
|
+
|
694
|
+
{"title":"Ruby Programming Language","desc":"\n A dynamic, open source programming language with a focus on\n simplicity and productivity. It has an elegant syntax that is\n natural to read and easy to write.\n "}
|
695
|
+
```
|