hnjobs_cli 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c3f98948d03611a2f682bb9808c297fbf3c45c50
4
+ data.tar.gz: 120aaeffb237de09cd60057f22974e8dd80c31bd
5
+ SHA512:
6
+ metadata.gz: e15f0c7180eea6a440e33b9e793946207085b4855d8cab41f0afbc0e8fc27f7b89fefc0d77ea9a013a17dadbac222b995bbe1ecbe20477c8f15148c6d7df6c83
7
+ data.tar.gz: 37553c2177615b6f2d7f4333f98b6dcbc8b8743d0adc843eb365e791a1e46c641f264b8312a1e80c0a53d3e439fe9c698aa91d1c5077a02e03a4fec02b060159
data/bin/hnjobs_cli ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'require_all'
4
+
5
+ require_all 'lib'
6
+
7
+ # require_relative '../config/environment'
8
+
9
+ HNjobsCLI.new.call
data/lib/controller.rb ADDED
@@ -0,0 +1,100 @@
1
+ class HNjobsCLI
2
+
3
+ # User Flow: First-Timer
4
+ # 1. user installs gem
5
+ # 2. user starts app
6
+ # 3. CLI says hi and provides instructions
7
+ # 4. user inputs url to scrape or uses default url
8
+ # 5. CLI scrapes url
9
+ # 6. CLI outputs list
10
+ # 7. user inputs number of job posting
11
+ # 8. CLI outputs further details about job posting
12
+ # 9. user returns to list via #list
13
+ # 10. user filters list by #filter
14
+ # 11. user scrapes new page via #scrape
15
+ # 12. user exits
16
+
17
+ # User interface
18
+ def call
19
+ puts greeting
20
+ scrape
21
+ input = ''
22
+ while input != 'exit'
23
+ input = gets.strip
24
+ case input
25
+ when -> (input) { input.to_i != 0 } # this proc lets you make comparisons inside case statements
26
+ job = Job.find_by_id(input.to_i)
27
+ if job
28
+ puts "\n\n" + job.description + "\n\n"
29
+ puts menu
30
+ else
31
+ puts "Out of range. Please input a number between 1 and #{Job.count}"
32
+ end
33
+ when 'list'
34
+ list
35
+ when 'exit'
36
+ puts "\n\nGoodbye!\n\n"
37
+ when 'scrape'
38
+ scrape
39
+ when 'filter'
40
+ filter
41
+ puts "\n\nEnter the number of a job posting to see more info."
42
+ else
43
+ puts 'Unknown command'
44
+ puts menu
45
+ end
46
+ end
47
+ end
48
+
49
+ # List jobs with numbers for reference
50
+ def list
51
+ puts "\n\n#{Job.count} job postings found\n\n"
52
+ Job.list.map do |job|
53
+ puts "#{job.id}. #{job.firstline}"
54
+ end
55
+ puts "\n\nEnter the number of a job posting to see more info."
56
+ end
57
+
58
+ # Scrape page and create jobs
59
+ def scrape
60
+ Job.reset
61
+ puts 'Enter a URL to scrape (or press enter for default):'
62
+ url = gets.strip
63
+ url = 'https://news.ycombinator.com/item?id=15601729' if url == ''
64
+ puts "Scraping...\n\n"
65
+ jobs_data = Scraper.scrape(url)
66
+ jobs_data.each_with_index do |job_data, i|
67
+ job = Job.new(job_data.merge({id: i+1}))
68
+ end
69
+ puts list
70
+ end
71
+
72
+ # Filter jobs
73
+ def filter
74
+ puts 'Enter keyword:'
75
+ keyword = gets.strip
76
+ Job.filter(keyword).each do |job|
77
+ puts "#{job.id} #{job.firstline}"
78
+ end
79
+ end
80
+
81
+ def greeting
82
+ <<~EOL
83
+ Hello! Welcome to the Hacker News Job Scraper.
84
+ I can distill an 'Ask HN: Who is hiring?' post down to its fine job postings.
85
+ Input URL to scrape:
86
+ EOL
87
+ end
88
+
89
+ def menu
90
+ <<~EOL
91
+ Available Commands:
92
+ Enter the number of a job posting to see its details
93
+ scrape //--> scrapes a new url and outputs another list of job postings
94
+ list //--> list job postings from latest scrape
95
+ filter //--> filter job postings by search terms
96
+ exit //--> exit the program
97
+ EOL
98
+ end
99
+
100
+ end
@@ -0,0 +1,3 @@
1
+ module Hnjobs
2
+ VERSION = "1.0.0"
3
+ end
data/lib/job.rb ADDED
@@ -0,0 +1,35 @@
1
+ class Job
2
+
3
+ @@all = []
4
+
5
+ attr_reader :company, :description, :firstline, :id
6
+
7
+ def initialize(options = {})
8
+ @id = options[:id]
9
+ @company = options[:company]
10
+ @firstline = options[:firstline]
11
+ @description = options[:description]
12
+ @@all << self
13
+ end
14
+
15
+ def self.find_by_id(id)
16
+ @@all.select { |job| job.id == id }.first
17
+ end
18
+
19
+ def self.filter(keyword)
20
+ @@all.select { |job| job.description.include?(keyword) }
21
+ end
22
+
23
+ def self.list
24
+ @@all
25
+ end
26
+
27
+ def self.count
28
+ @@all.count
29
+ end
30
+
31
+ def self.reset
32
+ @@all = []
33
+ end
34
+
35
+ end
data/lib/scraper.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+
4
+ class Scraper
5
+
6
+ # Assign nokogiri output to variable & search doc to populate jobs hash
7
+ def self.scrape(url)
8
+ @doc = ::Nokogiri::HTML(open(url))
9
+ @doc.css(".reply").remove
10
+ @doc.css(".comment").each_with_index.map do |comment, i|
11
+ unless comment.css(".c00").first === nil || comment.css(".c00").first === "" || !comment.css(".c00").first.to_s.include?('|') || comment.css(".c00").first.to_s.split("|").first.length > 150
12
+ company = comment.css(".c00").first.to_s.split("|").first.gsub(/<span class="c00">|<p>*|<a.*a>/, '').strip
13
+ firstline = comment.css(".c00").first.to_s.match(/.*\|*<p>/).to_s.gsub(/<span class="c00">|<p>*|<a.*a>/, '').strip
14
+ description = comment.css(":not(p)").first.text.strip
15
+ end
16
+ job_data = { company: company, firstline: firstline, description: description }
17
+ job_data unless company === nil || company === ""
18
+ end.compact
19
+ end
20
+
21
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hnjobs_cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - purple squirrel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.16.a
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.16.a
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: 'CLI app for checking monthly job postings on Ask HN: Who Is Hiring'
42
+ email:
43
+ - mikkanthrope@gmail.com
44
+ executables:
45
+ - hnjobs_cli
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - bin/hnjobs_cli
50
+ - lib/controller.rb
51
+ - lib/hnjobs/version.rb
52
+ - lib/job.rb
53
+ - lib/scraper.rb
54
+ homepage: https://github.com/squirrelnest/hnjobs_cli
55
+ licenses:
56
+ - MIT
57
+ metadata: {}
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 2.6.12
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Extracts job postings from Ycombinator Hacker News
78
+ test_files: []