livescore-parser 0.1.2
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 +7 -0
- data/bin/livescore-parser +42 -0
- data/lib/livescore-parser.rb +34 -0
- data/lib/livescore-parser/hash_helper.rb +62 -0
- data/lib/livescore-parser/parser.rb +46 -0
- data/lib/livescore-parser/writer.rb +45 -0
- data/pages.yml +1 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2e23b94b2804c5f214cb832551711871290a6878
|
4
|
+
data.tar.gz: 75cb546fb210cb8b856f63409f1d88a6a38b7a92
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a71dbc84a53c11683c26d1c033fddd790562997f2470a013a5d585545150623144f5d0deb4290b773490809c4d5641ded8701d050b2e3f471edc43b86a1a053e
|
7
|
+
data.tar.gz: d25fb25d2445b986b2bb5572232f81c876b5cdd7fc57e4eba2e7cae96ae0106104a5e0a6fee12c0ff6c7571a6ff3f38ef9483acb8d8c3ca82482bcd4c5fc6f65
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path("../lib", File.dirname(__FILE__)) # add library to load path
|
4
|
+
|
5
|
+
require 'livescore-parser'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
options = { :destination => '/home/hosting/scores/' }
|
9
|
+
OptionParser.new do |op|
|
10
|
+
op.banner = <<-eos
|
11
|
+
#{LivescoreParser::DESCRIPTION}
|
12
|
+
|
13
|
+
Usage: livescore-parser [options]
|
14
|
+
|
15
|
+
eos
|
16
|
+
|
17
|
+
op.on("-h", "--help") do
|
18
|
+
puts op.to_s
|
19
|
+
exit!
|
20
|
+
end
|
21
|
+
|
22
|
+
op.on("-v", "--version") do
|
23
|
+
puts LivescoreParser::VERSION
|
24
|
+
exit!
|
25
|
+
end
|
26
|
+
|
27
|
+
op.on("-c", "--pages PATH", "path to yml channel list") do |path|
|
28
|
+
options[:pages] = path
|
29
|
+
end
|
30
|
+
|
31
|
+
op.on("-d", "--destination PATH", "directory with XML files with parsed scores") do |path|
|
32
|
+
options[:destination] = path
|
33
|
+
end
|
34
|
+
end.parse!
|
35
|
+
|
36
|
+
begin
|
37
|
+
ARGV.clear
|
38
|
+
LivescoreParser.run!(options)
|
39
|
+
rescue Exception => ex
|
40
|
+
puts ex.message
|
41
|
+
exit!
|
42
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module LivescoreParser
|
2
|
+
|
3
|
+
#----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
VERSION = "0.1.0"
|
6
|
+
SUMMARY = "livescore parser"
|
7
|
+
DESCRIPTION = "Downloads livescore results to XML files"
|
8
|
+
|
9
|
+
require 'yaml'
|
10
|
+
require 'mechanize'
|
11
|
+
require 'nokogiri'
|
12
|
+
require 'pry'
|
13
|
+
|
14
|
+
require_relative 'livescore-parser/parser' # Parsing from website
|
15
|
+
require_relative 'livescore-parser/writer' # Writing from ruby hash to XML
|
16
|
+
|
17
|
+
# Initilizes Runner which controls all the magic stuff.
|
18
|
+
#
|
19
|
+
def self.run!(options = {})
|
20
|
+
@@options = options
|
21
|
+
data = Parser.new.run
|
22
|
+
Writer.new(data, @@options[:destination]).run
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def self.gem_root
|
28
|
+
File.expand_path '../..', __FILE__
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.selected_pages
|
32
|
+
@channels ||= YAML::load(File.open(@@options[:pages] || File.join(gem_root, 'pages.yml')))
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# USAGE: Hash.from_xml:(YOUR_XML_STRING)
|
2
|
+
require 'nokogiri'
|
3
|
+
# modified from http://stackoverflow.com/questions/1230741/convert-a-nokogiri-document-to-a-ruby-hash/1231297#1231297
|
4
|
+
|
5
|
+
class Hash
|
6
|
+
class << self
|
7
|
+
def from_xml(xml_io)
|
8
|
+
begin
|
9
|
+
result = Nokogiri::XML(xml_io)
|
10
|
+
return { result.root.name.to_sym => xml_node_to_hash(result.root)}
|
11
|
+
rescue Exception => e
|
12
|
+
# raise your custom exception here
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def xml_node_to_hash(node)
|
17
|
+
# If we are at the root of the document, start the hash
|
18
|
+
if node.element?
|
19
|
+
result_hash = {}
|
20
|
+
if node.attributes != {}
|
21
|
+
result_hash[:attributes] = {}
|
22
|
+
node.attributes.keys.each do |key|
|
23
|
+
result_hash[:attributes][node.attributes[key].name.to_sym] = prepare(node.attributes[key].value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
if node.children.size > 0
|
27
|
+
node.children.each do |child|
|
28
|
+
result = xml_node_to_hash(child)
|
29
|
+
|
30
|
+
if child.name == "text"
|
31
|
+
unless child.next_sibling || child.previous_sibling
|
32
|
+
return prepare(result)
|
33
|
+
end
|
34
|
+
elsif result_hash[child.name.to_sym]
|
35
|
+
if result_hash[child.name.to_sym].is_a?(Object::Array)
|
36
|
+
result_hash[child.name.to_sym] << prepare(result)
|
37
|
+
else
|
38
|
+
result_hash[child.name.to_sym] = [result_hash[child.name.to_sym]] << prepare(result)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
result_hash[child.name.to_sym] = prepare(result)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
return result_hash
|
46
|
+
else
|
47
|
+
return result_hash
|
48
|
+
end
|
49
|
+
else
|
50
|
+
return prepare(node.content.to_s)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def prepare(data)
|
55
|
+
(data.class == String && data.to_i.to_s == data) ? data.to_i : data
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_struct(struct_name)
|
60
|
+
Struct.new(struct_name,*keys).new(*values)
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module LivescoreParser
|
2
|
+
class Parser
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@agent = Mechanize.new
|
6
|
+
end
|
7
|
+
|
8
|
+
# Runs dynamic-sprites command.
|
9
|
+
#
|
10
|
+
def run
|
11
|
+
LivescoreParser.selected_pages.map do |name, url|
|
12
|
+
data = download(url)
|
13
|
+
{ name: name, data: data } unless data.nil?
|
14
|
+
end.compact
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def download(url)
|
20
|
+
page = Nokogiri::HTML(@agent.get(url).body)
|
21
|
+
data = build_hash page.css(".content tr").select{ |row| row.css('td').any? }
|
22
|
+
if data.empty?
|
23
|
+
puts "Missing data"
|
24
|
+
return nil
|
25
|
+
else
|
26
|
+
return data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# convert nokogiri html data to handy hash structure
|
31
|
+
def build_hash(data)
|
32
|
+
index = 0
|
33
|
+
data.map do |row|
|
34
|
+
index += 1
|
35
|
+
{
|
36
|
+
wiersz: index,
|
37
|
+
czas: row.css('td')[0].text.strip,
|
38
|
+
gracz1: row.css('td')[1].text.strip,
|
39
|
+
wynik1: row.css('td')[2].text.strip.match(/^[0-9\?]+/).to_s,
|
40
|
+
gracz2: row.css('td')[3].text.strip,
|
41
|
+
wynik2: row.css('td')[2].text.strip.match(/[0-9\?]+$/).to_s
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'builder'
|
2
|
+
require_relative 'hash_helper'
|
3
|
+
|
4
|
+
module LivescoreParser
|
5
|
+
class Writer
|
6
|
+
|
7
|
+
def initialize(scores, destination)
|
8
|
+
@scores = scores
|
9
|
+
@destination = destination
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
@scores.each do |page|
|
14
|
+
File.open(xml_path(page[:name]), "w+") do |file|
|
15
|
+
file.write(build_xml(page[:data]))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def xml_path(name)
|
23
|
+
File.join(@destination, "#{name}_#{Date.today.to_s}.xml")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Builds XML data from schedule Hash
|
27
|
+
def build_xml(data)
|
28
|
+
xml_builder = Builder::XmlMarkup.new( :indent => 2 )
|
29
|
+
xml_builder.instruct! :xml, :encoding => "UTF-8"
|
30
|
+
xml_builder.xml do |xml|
|
31
|
+
data.each do |score|
|
32
|
+
xml.node do |node|
|
33
|
+
node.wiersz score[:wiersz]
|
34
|
+
node.czas score[:czas]
|
35
|
+
node.gracz1 score[:gracz1]
|
36
|
+
node.wynik1 score[:wynik1]
|
37
|
+
node.gracz2 score[:gracz2]
|
38
|
+
node.wynik2 score[:wynik2]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
# {:wiersz=>1, :czas=>"19:45", :gracz1=>"Wycombe Wanderers", :wynik1=>"?", :gracz2=>"Burton Albion", :wynik2=>"?"}
|
data/pages.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
soccer: 'http://www.livescore.com/'
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: livescore-parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maciej Walusiak
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: builder
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mechanize
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
description: Downloads TV channel schedule in XML format
|
56
|
+
email: rabsztok@gmail.com
|
57
|
+
executables:
|
58
|
+
- livescore-parser
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- bin/livescore-parser
|
63
|
+
- lib/livescore-parser.rb
|
64
|
+
- lib/livescore-parser/hash_helper.rb
|
65
|
+
- lib/livescore-parser/parser.rb
|
66
|
+
- lib/livescore-parser/writer.rb
|
67
|
+
- pages.yml
|
68
|
+
homepage: https://github.com/Rabsztok/livescore-parser
|
69
|
+
licenses:
|
70
|
+
- GPL
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.2.0
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: TV Channel parser
|
92
|
+
test_files: []
|