module Baidu class TongjiService < ApplicationService attr_reader :client_id, :client_secret, :site_id # login、code、password、password_confirmation def initialize @client_id = "6dMO2kqKUaMZkBrMaUMxQSNAT49v0Mjq" @client_secret = "qvWqF33AOmGs1tPCgsROvis9EQCuNmd3" @site_id = 18657013 end def call end def init_overview_data_by(start_date = nil, end_date = nil) start_date = Time.now.prev_year.beginning_of_year if start_date.nil? end_date = Time.now Rails.logger.info("*********开始百度统计-概览:#{start_date}-#{end_date}*********") sql_connection = ActiveRecord::Base.connection sql_connection.begin_db_transaction # 如果存在数据 先清空 # sql_connection.execute("delete from daily_platform_statistics where date between '#{start_date}' and '#{end_date}'") multiple_days_data = overview_multiple_days_data(start_date, end_date) if multiple_days_data.present? sql = "replace into daily_platform_statistics (date,pv,visitor,ip,created_at,updated_at) values #{multiple_days_data.join(",")}" sql_connection.execute(sql) end sql_connection.commit_db_transaction Rails.logger.info("*********结束百度统计-概览:#{start_date}-#{end_date}*********") end def init_source_from_data_by(start_date = nil, end_date = nil) start_date = Time.now.prev_year.beginning_of_year if start_date.nil? end_date = Time.now Rails.logger.info("*********开始百度统计-来源:#{start_date}-#{end_date}*********") source_from_batch_add(start_date, end_date) Rails.logger.info("*********结束百度统计-来源:#{start_date}-#{end_date}*********") end # 按日期获取来源数据 def source_from_batch_add(start_date,end_date) # 补充更新开始时间的当天数据 source_from_by_date(start_date) diff_days(start_date, end_date).times.each do |t| new_start_date = start_date + (t + 1).days source_from_by_date(new_start_date) end # 补充更新最后时间一天数据 source_from_by_date(end_date) end # 按天获取来源数据 def source_from_by_date(start_date) return [] unless access_token.present? && start_date.present? source_from_data = api("source/all/a", start_date, start_date, "pv_count,visitor_count,ip_count") source_from = [] source_from_data['items'][1].each_with_index do |source, index| source_from.push(((source[0].to_f / source_from_data['sum'][0][0].to_f) * 100).round(2)) end daily_statistic = DailyPlatformStatistic.find_or_initialize_by(date: start_date) daily_statistic.source_through = source_from[0] daily_statistic.source_link = source_from[1] daily_statistic.source_search = source_from[2] daily_statistic.source_custom = source_from[3] daily_statistic.save end def diff_days(start_date, end_date) (end_date.beginning_of_day.to_i - start_date.beginning_of_day.to_i) / (24 * 3600) end def overview_batch_add(start_date, end_date) return [] unless access_token.present? && start_date.present? && end_date.present? start_date = Time.now - 1.days if start_date.strftime("%Y%m%d") == end_date.strftime("%Y%m%d") overview_data = api("overview/getTimeTrendRpt", start_date, end_date, "pv_count,visitor_count,ip_count") overview_data['items'][0].each_with_index do |date, index| pv = overview_data['items'][1][index][0] visitor = overview_data['items'][1][index][1] ip = overview_data['items'][1][index][2] job_date = date[0].to_s.gsub("/", "-") daily_statistic = DailyPlatformStatistic.find_or_initialize_by(date: job_date) daily_statistic.date = job_date daily_statistic.pv = pv daily_statistic.visitor = visitor daily_statistic.ip = ip daily_statistic.save end overview_data end def overview_multiple_days_data(start_date, end_date) return [] unless access_token.present? && start_date.present? && end_date.present? overview_data = api("overview/getTimeTrendRpt", start_date, end_date, "pv_count,visitor_count,ip_count") data = [] created_at = Time.now.strftime("%Y-%m-%d 00:00:00") overview_data['items'][0].each_with_index do |date, index| pv = overview_data['items'][1][index][0] visitor = overview_data['items'][1][index][1] ip = overview_data['items'][1][index][2] data.push("('#{date[0].to_s.gsub("/", "-")}', #{pv.to_s.gsub("--","0")}, #{visitor.to_s.gsub("--","0")}, #{ip.to_s.gsub("--","0")},\"#{created_at}\",\"#{created_at}\")") end data end def code_url "http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=#{client_id}&redirect_uri=oob&scope=basic&display=popup" end def oauth_url(code) "http://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=#{code}&client_id=#{client_id}&client_secret=#{client_secret}&redirect_uri=oob" end def get_access_token(code) uri = URI.parse(oauth_url(code)) response = Net::HTTP.get_response(uri) Rails.logger.info "baidu_tongji_auth response.body ===== #{response.body}" if response.code.to_i == 200 data = JSON.parse(response.body) access_token = data['access_token'] refresh_token = data['refresh_token'] expires_in = data['expires_in'] if access_token.present? Rails.cache.write("baidu_tongji_auth/access_token", access_token, expires_in: expires_in) Rails.cache.write("baidu_tongji_auth/refresh_token", refresh_token, expires_in: 1.year) end end end def refresh_access_token url = "http://openapi.baidu.com/oauth/2.0/token?grant_type=refresh_token&refresh_token=#{refresh_token}&client_id=#{client_id}&client_secret=#{client_secret}" uri = URI.parse(url) response = Net::HTTP.get_response(uri) Rails.logger.info "baidu_tongji_auth response.body ===== #{response.body}" if response.code.to_i == 200 data = JSON.parse(response.body) access_token = data['access_token'] refresh_token = data['refresh_token'] expires_in = data['expires_in'] if access_token.present? Rails.cache.write("baidu_tongji_auth/access_token", access_token, expires_in: expires_in) Rails.cache.write("baidu_tongji_auth/refresh_token", refresh_token, expires_in: 1.year) end end end def access_token access_token = Rails.cache.read("baidu_tongji_auth/access_token") if access_token.blank? && refresh_token.present? refresh_access_token access_token = Rails.cache.read("baidu_tongji_auth/access_token") end access_token end def refresh_token refresh_token = Rails.cache.read("baidu_tongji_auth/refresh_token") # 如果刷新token失效,access_token也重置 if refresh_token.blank? Rails.cache.delete("baidu_tongji_auth/access_token") end refresh_token end # 网站概况(趋势数据) def api_overview start_date = Time.now.beginning_of_week end_date = Time.now start_date = Time.now - 1.days if start_date.strftime("%Y%m%d") == end_date.strftime("%Y%m%d") api("overview/getTimeTrendRpt", start_date, end_date, "pv_count,visitor_count,ip_count") end # 网站概况(来源网站、搜索词、入口页面、受访页面) def api_overview_getCommonTrackRpt start_date = Time.now.beginning_of_week end_date = Time.now api("overview/getCommonTrackRpt", start_date, end_date, "pv_count") end # 全部来源 def source_from start_date = Time.now.beginning_of_week end_date = Time.now api("source/all/a", start_date, end_date, "pv_count,visitor_count,ip_count") end def api(api_method, start_date, end_date, metrics = nil) start_date_fmt = start_date.strftime("%Y%m%d") end_date_fmt = end_date.strftime("%Y%m%d") api_url = "https://openapi.baidu.com/rest/2.0/tongji/report/getData?access_token=#{access_token}&site_id=#{site_id}&method=#{api_method}&start_date=#{start_date_fmt}&end_date=#{end_date_fmt}&metrics=#{metrics}" data = url_http_post(api_url, {}) data['result'] end def url_http_post(api_url, params) Rails.logger.info "api_url==#{api_url}" uri = URI.parse(api_url) http = Net::HTTP.new uri.host, uri.port http.open_timeout = 60 http.read_timeout = 60 if uri.scheme == 'https' http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.use_ssl = true end begin request = Net::HTTP::Post.new(uri) request.set_form_data(params) if params.present? request['Content-Type'] = 'application/json;charset=utf-8' # request['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8' response = http.start { |http| http.request(request) } Rails.logger.info "api response.body==#{response.body}" JSON.parse response.body rescue => err Rails.logger.error("#############api_url:#{api_url},error:#{err.message.size}") # Rails.logger.error("#############api_url:#{api_url},error:#{err.message}") return {} end end end end