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 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=&gt;1, :czas=&gt;"19:45", :gracz1=&gt;"Wycombe Wanderers", :wynik1=&gt;"?", :gracz2=&gt;"Burton Albion", :wynik2=&gt;"?"}
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: []