livescore-parser 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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: []