-
Notifications
You must be signed in to change notification settings - Fork 5
/
user.rb
111 lines (87 loc) 路 2.26 KB
/
user.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# frozen_string_literal: true
class Instagrammer::User
include Capybara::DSL
include Instagrammer::Utils
attr_reader :posts
def initialize(username)
@username = username.delete_prefix("@")
@data = nil
@posts = []
end
def public?
get_data unless @data
@status == :public
end
def meta
get_data unless @data
if @status == :not_found
raise Instagrammer::UserNotFound.new("Private account: #{@username}")
else
@meta
end
end
def follower_count
meta[:followers]
end
def following_count
meta[:following]
end
def post_count
meta[:posts]
end
def data
get_data unless @data
case @status
when :private then raise Instagrammer::PrivateAccount.new("Private account: #{@username}")
when :not_found then raise Instagrammer::UserNotFound.new("User not found: #{@username}")
when :invalid then raise Instagrammer::UserInvalid.new("User invalid: #{@username}")
else @data
end
end
def name
data["name"]
end
def username
data["alternateName"].delete_prefix("@")
end
def avatar
data["image"]
end
def bio
data["description"]
end
def url
data["mainEntityofPage"]["@id"]
end
SHORTCODE_RE = /\/p\/(\S+)\/$/
def get_posts(limit)
shortcodes = []
i = 0
visit "https://www.instagram.com/#{@username}/"
while i < limit
post_links = page.all(:post_link)
if limit > post_links.size
page.execute_script "window.scrollTo(0,document.body.scrollHeight);"
post_links = page.all(:post_link)
end
shortcode = post_links[i]["href"].match(SHORTCODE_RE)[1]
shortcodes << shortcode
i += 1
end
@posts = shortcodes.collect { |code| Instagrammer::Post.new(code) }
end
private
def get_data
visit "https://www.instagram.com/#{@username}/"
@status = get_page_status
@meta = get_metadata unless @status == :not_found
if @status == :public
node = page.first(:json_ld, visible: false)
@data = JSON.parse(node.text(:all))
end
end
META_RE = /(?<followers>\S+) Followers, (?<following>\S+) Following, (?<posts>\S+) Posts/
def get_metadata
@meta = page.first(:meta_description, visible: false)["content"].match META_RE
end
end