doctor_finder 0.1.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 +7 -0
- data/.gitignore +8 -0
- data/Gemfile +6 -0
- data/README.md +41 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/doctor_finder +5 -0
- data/bin/setup +8 -0
- data/doctor_finder.gemspec +28 -0
- data/lib/doctor_finder/cli.rb +75 -0
- data/lib/doctor_finder/doctor.rb +28 -0
- data/lib/doctor_finder/scraper.rb +38 -0
- data/lib/doctor_finder/version.rb +3 -0
- data/lib/doctor_finder.rb +9 -0
- data/spec.md +9 -0
- metadata +114 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 7d57e02cabe9f40b3dbd4e6a26dc5913598eb48d
|
|
4
|
+
data.tar.gz: a518f2fa4120d6605489c67b2dc4f0149000027d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c1c7508db94cd467f0713c0a3d5e1cdc73fb75833328bb8f7539f99988643b89e5f28816e43b70ae9ebc09d922a73f7a09debbe2726b9fbe3b08b296d618f187
|
|
7
|
+
data.tar.gz: '09e89fefe4fe660d43390ad5a3e50766464668e0007044e802cab310196cf729bea46aede4f676bcfca7fcdcd698d08e99cf54e56b00bed198fa111c95be9641'
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# DoctorFinder
|
|
2
|
+
|
|
3
|
+
DoctorFinder is a Ruby Gem that searches for doctors in a given zipcode. The CLI asks ths user for a zip code and then scrapes data from [https://www.zocdoc.com/](https://www.zocdoc.com/).
|
|
4
|
+
|
|
5
|
+
Once zocdoc is scraped, the user is presented with a list of doctors more or less in or near the requsted zipcode. The user can then select a particular doctor to see more details about that doctor.
|
|
6
|
+
|
|
7
|
+
This CLI project was done as part of the requirements for the Web Developer Track at [The Flatiron School](http://flatironschool.com/).
|
|
8
|
+
|
|
9
|
+
## License
|
|
10
|
+
|
|
11
|
+
DoctorFinder is licensed under the [MIT License](https://mit-license.org).
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Add this line to your application's Gemfile:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
gem 'doctor_finder'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
And then execute:
|
|
22
|
+
|
|
23
|
+
$ bundle
|
|
24
|
+
|
|
25
|
+
Or install it yourself as:
|
|
26
|
+
|
|
27
|
+
$ gem install doctor_finder
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
This is a CLI. Once you run the command 'doctor_finder' from the command line, you will be asked to enter a valid zip code. As long as the zipcode begins with give digits, it will perform a search and return a list of doctors. You can then enter a number corresponding to the doctor you are interested in for more details about that doctor. After that, the process repeats until you exit.
|
|
32
|
+
|
|
33
|
+
## Development
|
|
34
|
+
|
|
35
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
36
|
+
|
|
37
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
38
|
+
|
|
39
|
+
## Contributing
|
|
40
|
+
|
|
41
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bthooper/doctor_finder.
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "doctor_finder"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/doctor_finder
ADDED
data/bin/setup
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require "doctor_finder/version"
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "doctor_finder"
|
|
8
|
+
spec.version = DoctorFinder::VERSION
|
|
9
|
+
spec.authors = ["Bryan Hooper"]
|
|
10
|
+
spec.email = ["bryan@lindsayfarm.net"]
|
|
11
|
+
|
|
12
|
+
spec.summary = %q{DoctorFinder finds doctors.}
|
|
13
|
+
spec.description = %q{DoctorFinder is a CLI that asks for a zipcode and the returns a list of doctors.}
|
|
14
|
+
spec.homepage = "https://github.com/bthooper/doctor_finder"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
|
18
|
+
end
|
|
19
|
+
spec.bindir = "exe"
|
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
21
|
+
spec.require_paths = ["lib"]
|
|
22
|
+
|
|
23
|
+
spec.add_runtime_dependency "nokogiri"
|
|
24
|
+
|
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
27
|
+
spec.add_development_dependency "pry"
|
|
28
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# CLI Main file defining the CLI class
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
class DoctorFinder::CLI
|
|
5
|
+
|
|
6
|
+
def call
|
|
7
|
+
puts "\nWelcome to Hooper's Doctor Finder."
|
|
8
|
+
puts "\nWith HDF you can retrieve a list of doctors by zipcode and then get more details about a particular doctor on that list. It's easy!"
|
|
9
|
+
show_list(get_zipcode)
|
|
10
|
+
get_choice_from_list
|
|
11
|
+
farewell
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def get_zipcode
|
|
15
|
+
# Gets a valid zip code from the user
|
|
16
|
+
zip = ""
|
|
17
|
+
while !iszipcode?(zip)
|
|
18
|
+
puts "\nPlease enter a valid zipcode:"
|
|
19
|
+
zip = gets.chomp[0..4]
|
|
20
|
+
end
|
|
21
|
+
zip
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def iszipcode?(zipcode)
|
|
25
|
+
# Provides a basic level of validation for user input of zipcode.
|
|
26
|
+
if zipcode.length == 5 && zipcode.scan(/\D/).empty?
|
|
27
|
+
true
|
|
28
|
+
else
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def show_list(zipcode)
|
|
34
|
+
# Calls scraper and prints a list of doctors based on the zip code entered by the user.
|
|
35
|
+
DoctorFinder::Doctor.clear
|
|
36
|
+
docs = DoctorFinder::Scraper.scrape_by_zipcode(zipcode)
|
|
37
|
+
docs.each.with_index(1) do |doc, i|
|
|
38
|
+
puts "#{i}. #{doc.name} - #{doc.speciality} - #{doc.city}, #{doc.state} #{doc.zip}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def get_choice_from_list
|
|
43
|
+
# Gets a valid choice from the list of Doctors.
|
|
44
|
+
|
|
45
|
+
choice = nil
|
|
46
|
+
|
|
47
|
+
while choice != "exit" && choice != "q"
|
|
48
|
+
puts "\n[1..#{DoctorFinder::Doctor.all.length}] Select Doctor | [zip] Start over with new zipcode | [exit] To quit"
|
|
49
|
+
choice = gets.chomp
|
|
50
|
+
if choice.to_i > 0 && choice.to_i < DoctorFinder::Doctor.all.length+1
|
|
51
|
+
doc = DoctorFinder::Scraper.scrape_for_details(DoctorFinder::Doctor.all[choice.to_i-1])
|
|
52
|
+
puts "======================================\n"
|
|
53
|
+
puts doc.name
|
|
54
|
+
puts doc.street
|
|
55
|
+
puts doc.city + ', ' + doc.state + ' ' + doc.zip
|
|
56
|
+
puts "--------------------------------------\n"
|
|
57
|
+
puts "Areas of Specialty:"
|
|
58
|
+
puts doc.areas
|
|
59
|
+
puts doc.details
|
|
60
|
+
elsif choice == "zip"
|
|
61
|
+
show_list(get_zipcode)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def farewell
|
|
67
|
+
# Tells the user goodbye.
|
|
68
|
+
puts "\n\nThank you for using Hooper's Doctor Finder. This was an educational experiment, and I learned a lot. At first it seemed hard, but then it got easier.\n\nSee you next time.\n\n\n\n"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# The Doctor class
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
class DoctorFinder::Doctor
|
|
5
|
+
|
|
6
|
+
attr_accessor :name, :url, :speciality, :street, :city, :state, :zip, :details, :areas
|
|
7
|
+
|
|
8
|
+
@@all = []
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@@all << self
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.all
|
|
15
|
+
@@all
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.clear
|
|
19
|
+
@@all = []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# The Scraper class
|
|
2
|
+
#
|
|
3
|
+
#
|
|
4
|
+
|
|
5
|
+
class DoctorFinder::Scraper
|
|
6
|
+
|
|
7
|
+
BASE_URL = "https://www.zocdoc.com/"
|
|
8
|
+
|
|
9
|
+
def self.scrape_by_zipcode(zipcode)
|
|
10
|
+
html = Nokogiri::HTML(open("#{BASE_URL}search?address=#{zipcode}&insurance_carrier=-1&day_filter=AnyDay&gender=-1&language=-1&offset=0&insurance_plan=-1&reason_visit=75&after_5pm=false&before_10am=false&sees_children=false&sort_type=Default&dr_specialty=153&"))
|
|
11
|
+
slice = html.css('.js-prof-row-container')
|
|
12
|
+
slice.each do |doctor| # will go through the HTML and create new doctor instances
|
|
13
|
+
doc = DoctorFinder::Doctor.new
|
|
14
|
+
doc.name = doctor.css('.js-profile-link').text.strip.gsub("\n", ' ').squeeze(' ')
|
|
15
|
+
doc.speciality = doctor.css('.ch-prof-row-speciality').text.strip
|
|
16
|
+
doc.url = BASE_URL + doctor.css('.js-profile-link')[0]['href']
|
|
17
|
+
address = doctor.css('.js-search-prof-row-address').text.strip
|
|
18
|
+
doc.street = address.slice(/^\d+[ ][\w+[ ]]+/) # To format the text correctly, had to use some regex
|
|
19
|
+
doc.city = address[/[ ][ ]+[\w+[.]*[ ]]*[,]/].strip.chop
|
|
20
|
+
doc.state = address[/[A-Z][A-Z]/]
|
|
21
|
+
doc.zip = address[/\d{5}/]
|
|
22
|
+
end
|
|
23
|
+
DoctorFinder::Doctor.all
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.scrape_for_details(doctor)
|
|
27
|
+
html = Nokogiri::HTML(open(doctor.url))
|
|
28
|
+
doctor.details = html.css('.profile-professional-statement').text.squeeze(' ')
|
|
29
|
+
if doctor.details.strip == ""
|
|
30
|
+
doctor.details = "No further details were available."
|
|
31
|
+
end
|
|
32
|
+
doctor.areas = html.css('li.specialty').text.squeeze(" ").gsub("\r\n \r\n ", "\r\n").lstrip
|
|
33
|
+
doctor
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
data/spec.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
pecifications for the CLI Assessment
|
|
2
|
+
|
|
3
|
+
Specs:
|
|
4
|
+
- [x] Have a CLI for interfacing with the application
|
|
5
|
+
I have an executable file that instantiates a CLI object that interacts with the user and calls other methods.
|
|
6
|
+
- [x] Pull data from an external source
|
|
7
|
+
I pull a list of doctors from Zocdoc.com.
|
|
8
|
+
- [x] Implement both list and detail views
|
|
9
|
+
I pull additional details about a specfic doctor by calling open-uri on a specific url for that doctor.
|
metadata
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: doctor_finder
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Bryan Hooper
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-03-06 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: nokogiri
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bundler
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.16'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.16'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '10.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '10.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: pry
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
description: DoctorFinder is a CLI that asks for a zipcode and the returns a list
|
|
70
|
+
of doctors.
|
|
71
|
+
email:
|
|
72
|
+
- bryan@lindsayfarm.net
|
|
73
|
+
executables: []
|
|
74
|
+
extensions: []
|
|
75
|
+
extra_rdoc_files: []
|
|
76
|
+
files:
|
|
77
|
+
- ".gitignore"
|
|
78
|
+
- Gemfile
|
|
79
|
+
- README.md
|
|
80
|
+
- Rakefile
|
|
81
|
+
- bin/console
|
|
82
|
+
- bin/doctor_finder
|
|
83
|
+
- bin/setup
|
|
84
|
+
- doctor_finder.gemspec
|
|
85
|
+
- lib/doctor_finder.rb
|
|
86
|
+
- lib/doctor_finder/cli.rb
|
|
87
|
+
- lib/doctor_finder/doctor.rb
|
|
88
|
+
- lib/doctor_finder/scraper.rb
|
|
89
|
+
- lib/doctor_finder/version.rb
|
|
90
|
+
- spec.md
|
|
91
|
+
homepage: https://github.com/bthooper/doctor_finder
|
|
92
|
+
licenses: []
|
|
93
|
+
metadata: {}
|
|
94
|
+
post_install_message:
|
|
95
|
+
rdoc_options: []
|
|
96
|
+
require_paths:
|
|
97
|
+
- lib
|
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
|
+
requirements:
|
|
105
|
+
- - ">="
|
|
106
|
+
- !ruby/object:Gem::Version
|
|
107
|
+
version: '0'
|
|
108
|
+
requirements: []
|
|
109
|
+
rubyforge_project:
|
|
110
|
+
rubygems_version: 2.6.13
|
|
111
|
+
signing_key:
|
|
112
|
+
specification_version: 4
|
|
113
|
+
summary: DoctorFinder finds doctors.
|
|
114
|
+
test_files: []
|