{"action":"created","comment":{"url":"https://api.github.com/repos/xiachufang/bandit-client/pulls/comments/74538495","id":74538495,"diff_hunk":"@@ -0,0 +1,109 @@\n+# coding: utf-8\n+import requests\n+import datetime\n+import simplejson\n+import hashlib\n+\n+\n+def compute_sign(d, secret_key):\n+    md5_str = ''\n+    for key, value in sorted(d.items(), key=lambda x: x[0]):\n+        if isinstance(value, unicode):\n+            value = value.encode('utf8')\n+        else:\n+            value = str(value)\n+        if isinstance(value, str):\n+            md5_str += \"%s%s\" % (key, value)\n+    md5_str += str(secret_key)\n+    sign = hashlib.md5(md5_str).hexdigest()\n+    return sign\n+\n+\n+class PostError(Exception):\n+\n+    def __init__(self, arg):\n+        self.args = [arg]\n+\n+\n+class BanditClient(object):\n+\n+    def __init__(self, host, public_key, secret_key, max_queue_length=100, max_seconds=86400):\n+        self.public_key = public_key\n+        self.secret_key = secret_key\n+        self.host = host\n+        self.max_queue_length = max_queue_length\n+        self.max_seconds = max_seconds\n+\n+    def create_instance(self):\n+        return BanditClientInstance(self)\n+\n+\n+class BanditSendQueue(object):\n+\n+    def __init__(self, url):\n+        self.url = url\n+        self.clear()\n+\n+    def clear(self):\n+        self.queue = []\n+        self.last_send_time = datetime.datetime.now()\n+\n+\n+class BanditClientInstance(object):\n+\n+    def __init__(self, bc):\n+        self.host_info = bc\n+        self.click_queue = BanditSendQueue(\"%s/api/click.json\" % self.host_info.host)\n+        self.show_queue = BanditSendQueue(\"%s/api/show.json\" % self.host_info.host)\n+        self.adjust_url = \"%s/api/adjust.json\" % self.host_info.host\n+        self.max_queue_length = bc.max_queue_length\n+        self.max_seconds = bc.max_seconds\n+\n+    def __del__(self):\n+        if self.click_queue.queue:\n+            self.push(self.click_queue)\n+        if self.show_queue.queue:\n+            self.push(self.show_queue)\n+\n+    def _signature(self, data):\n+        return dict(zip(data.keys() + ['signature'],\n+                        data.values() + [compute_sign(data, self.host_info.secret_key)]))\n+\n+    def click(self, query, query_time, target, sk):\n+        if type(query_time) != str:\n+            query_time = query_time.strftime(\"%Y-%m-%d %H:%M:%S\")\n+        self.add_queue(self.click_queue, {'query': query,","path":"bandit_client/client.py","position":75,"original_position":75,"commit_id":"0232392aec36054d21975001da6f9e14d6110e94","original_commit_id":"0232392aec36054d21975001da6f9e14d6110e94","user":{"login":"yangyangxcf","id":17398258,"avatar_url":"https://avatars.githubusercontent.com/u/17398258?v=3","gravatar_id":"","url":"https://api.github.com/users/yangyangxcf","html_url":"https://github.com/yangyangxcf","followers_url":"https://api.github.com/users/yangyangxcf/followers","following_url":"https://api.github.com/users/yangyangxcf/following{/other_user}","gists_url":"https://api.github.com/users/yangyangxcf/gists{/gist_id}","starred_url":"https://api.github.com/users/yangyangxcf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yangyangxcf/subscriptions","organizations_url":"https://api.github.com/users/yangyangxcf/orgs","repos_url":"https://api.github.com/users/yangyangxcf/repos","events_url":"https://api.github.com/users/yangyangxcf/events{/privacy}","received_events_url":"https://api.github.com/users/yangyangxcf/received_events","type":"User","site_admin":false},"body":"一个url可能对应多个调权，比如商品可能出现在商品搜索，也可能出现在大家都在买","created_at":"2016-08-12T03:48:33Z","updated_at":"2016-08-12T03:48:33Z","html_url":"https://github.com/xiachufang/bandit-client/pull/1#discussion_r74538495","pull_request_url":"https://api.github.com/repos/xiachufang/bandit-client/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/xiachufang/bandit-client/pulls/comments/74538495"},"html":{"href":"https://github.com/xiachufang/bandit-client/pull/1#discussion_r74538495"},"pull_request":{"href":"https://api.github.com/repos/xiachufang/bandit-client/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/xiachufang/bandit-client/pulls/1","id":80411427,"html_url":"https://github.com/xiachufang/bandit-client/pull/1","diff_url":"https://github.com/xiachufang/bandit-client/pull/1.diff","patch_url":"https://github.com/xiachufang/bandit-client/pull/1.patch","issue_url":"https://api.github.com/repos/xiachufang/bandit-client/issues/1","number":1,"state":"closed","locked":false,"title":"init","user":{"login":"yangyangxcf","id":17398258,"avatar_url":"https://avatars.githubusercontent.com/u/17398258?v=3","gravatar_id":"","url":"https://api.github.com/users/yangyangxcf","html_url":"https://github.com/yangyangxcf","followers_url":"https://api.github.com/users/yangyangxcf/followers","following_url":"https://api.github.com/users/yangyangxcf/following{/other_user}","gists_url":"https://api.github.com/users/yangyangxcf/gists{/gist_id}","starred_url":"https://api.github.com/users/yangyangxcf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yangyangxcf/subscriptions","organizations_url":"https://api.github.com/users/yangyangxcf/orgs","repos_url":"https://api.github.com/users/yangyangxcf/repos","events_url":"https://api.github.com/users/yangyangxcf/events{/privacy}","received_events_url":"https://api.github.com/users/yangyangxcf/received_events","type":"User","site_admin":false},"body":"# 点击调权client\r\n\r\n* 安装最新的 bandit_client\r\n\r\n    ```bash\r\n    sudo pip install bandit_client\r\n    ```\r\n\r\n* 然后这样用\r\n\r\n    ```python\r\n    import bandit_client\r\n    client = bandit_client.BanditClient(host, public_key, secret_key, max_queue_length, max_seconds)\r\n    # max_queue_length 对click和show会各自维护一个队列，max_queue_length为队列最大长度，默认为100 \r\n    # max_seconds 距离上次post秒数超过max_seconds时，即使队列长度没有达到max_queue_length也进行post，默认为86400（一天\r\n    instance = client.create_instance()\r\n    # 每一个instance中维护一个click队列，一个show队列\r\n    instance.click(query, query_time, target, sk) \r\n    # query: 关键词，类型为str \r\n    # query_time: 时间，类型为datetime或str \r\n    # target: 点击项目的编号，类型为str \r\n    # sk: 用户sk，类型为str \r\n    instance.adjust(hits, query)                                                                                                                                                                            \r\n    # hits: 待调权list, list中元素为dict，包含id和total_score两个key，id类型为str，total_score为float\r\n    # query: 关键词\r\n    ```\r\n","created_at":"2016-08-08T08:24:35Z","updated_at":"2016-08-12T03:48:33Z","closed_at":"2016-08-09T02:21:59Z","merged_at":"2016-08-09T02:21:59Z","merge_commit_sha":"329a2fcf721a01996247d470ad26bb6bf37875c3","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/xiachufang/bandit-client/pulls/1/commits","review_comments_url":"https://api.github.com/repos/xiachufang/bandit-client/pulls/1/comments","review_comment_url":"https://api.github.com/repos/xiachufang/bandit-client/pulls/comments{/number}","comments_url":"https://api.github.com/repos/xiachufang/bandit-client/issues/1/comments","statuses_url":"https://api.github.com/repos/xiachufang/bandit-client/statuses/0232392aec36054d21975001da6f9e14d6110e94","head":{"label":"yangyangxcf:init1","ref":"init1","sha":"0232392aec36054d21975001da6f9e14d6110e94","user":{"login":"yangyangxcf","id":17398258,"avatar_url":"https://avatars.githubusercontent.com/u/17398258?v=3","gravatar_id":"","url":"https://api.github.com/users/yangyangxcf","html_url":"https://github.com/yangyangxcf","followers_url":"https://api.github.com/users/yangyangxcf/followers","following_url":"https://api.github.com/users/yangyangxcf/following{/other_user}","gists_url":"https://api.github.com/users/yangyangxcf/gists{/gist_id}","starred_url":"https://api.github.com/users/yangyangxcf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yangyangxcf/subscriptions","organizations_url":"https://api.github.com/users/yangyangxcf/orgs","repos_url":"https://api.github.com/users/yangyangxcf/repos","events_url":"https://api.github.com/users/yangyangxcf/events{/privacy}","received_events_url":"https://api.github.com/users/yangyangxcf/received_events","type":"User","site_admin":false},"repo":{"id":64274165,"name":"bandit-client","full_name":"yangyangxcf/bandit-client","owner":{"login":"yangyangxcf","id":17398258,"avatar_url":"https://avatars.githubusercontent.com/u/17398258?v=3","gravatar_id":"","url":"https://api.github.com/users/yangyangxcf","html_url":"https://github.com/yangyangxcf","followers_url":"https://api.github.com/users/yangyangxcf/followers","following_url":"https://api.github.com/users/yangyangxcf/following{/other_user}","gists_url":"https://api.github.com/users/yangyangxcf/gists{/gist_id}","starred_url":"https://api.github.com/users/yangyangxcf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yangyangxcf/subscriptions","organizations_url":"https://api.github.com/users/yangyangxcf/orgs","repos_url":"https://api.github.com/users/yangyangxcf/repos","events_url":"https://api.github.com/users/yangyangxcf/events{/privacy}","received_events_url":"https://api.github.com/users/yangyangxcf/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/yangyangxcf/bandit-client","description":null,"fork":true,"url":"https://api.github.com/repos/yangyangxcf/bandit-client","forks_url":"https://api.github.com/repos/yangyangxcf/bandit-client/forks","keys_url":"https://api.github.com/repos/yangyangxcf/bandit-client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yangyangxcf/bandit-client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yangyangxcf/bandit-client/teams","hooks_url":"https://api.github.com/repos/yangyangxcf/bandit-client/hooks","issue_events_url":"https://api.github.com/repos/yangyangxcf/bandit-client/issues/events{/number}","events_url":"https://api.github.com/repos/yangyangxcf/bandit-client/events","assignees_url":"https://api.github.com/repos/yangyangxcf/bandit-client/assignees{/user}","branches_url":"https://api.github.com/repos/yangyangxcf/bandit-client/branches{/branch}","tags_url":"https://api.github.com/repos/yangyangxcf/bandit-client/tags","blobs_url":"https://api.github.com/repos/yangyangxcf/bandit-client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yangyangxcf/bandit-client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yangyangxcf/bandit-client/git/refs{/sha}","trees_url":"https://api.github.com/repos/yangyangxcf/bandit-client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yangyangxcf/bandit-client/statuses/{sha}","languages_url":"https://api.github.com/repos/yangyangxcf/bandit-client/languages","stargazers_url":"https://api.github.com/repos/yangyangxcf/bandit-client/stargazers","contributors_url":"https://api.github.com/repos/yangyangxcf/bandit-client/contributors","subscribers_url":"https://api.github.com/repos/yangyangxcf/bandit-client/subscribers","subscription_url":"https://api.github.com/repos/yangyangxcf/bandit-client/subscription","commits_url":"https://api.github.com/repos/yangyangxcf/bandit-client/commits{/sha}","git_commits_url":"https://api.github.com/repos/yangyangxcf/bandit-client/git/commits{/sha}","comments_url":"https://api.github.com/repos/yangyangxcf/bandit-client/comments{/number}","issue_comment_url":"https://api.github.com/repos/yangyangxcf/bandit-client/issues/comments{/number}","contents_url":"https://api.github.com/repos/yangyangxcf/bandit-client/contents/{+path}","compare_url":"https://api.github.com/repos/yangyangxcf/bandit-client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yangyangxcf/bandit-client/merges","archive_url":"https://api.github.com/repos/yangyangxcf/bandit-client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yangyangxcf/bandit-client/downloads","issues_url":"https://api.github.com/repos/yangyangxcf/bandit-client/issues{/number}","pulls_url":"https://api.github.com/repos/yangyangxcf/bandit-client/pulls{/number}","milestones_url":"https://api.github.com/repos/yangyangxcf/bandit-client/milestones{/number}","notifications_url":"https://api.github.com/repos/yangyangxcf/bandit-client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yangyangxcf/bandit-client/labels{/name}","releases_url":"https://api.github.com/repos/yangyangxcf/bandit-client/releases{/id}","deployments_url":"https://api.github.com/repos/yangyangxcf/bandit-client/deployments","created_at":"2016-07-27T03:30:07Z","updated_at":"2016-07-18T04:11:43Z","pushed_at":"2016-08-11T10:51:17Z","git_url":"git://github.com/yangyangxcf/bandit-client.git","ssh_url":"git@github.com:yangyangxcf/bandit-client.git","clone_url":"https://github.com/yangyangxcf/bandit-client.git","svn_url":"https://github.com/yangyangxcf/bandit-client","homepage":null,"size":2,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"xiachufang:master","ref":"master","sha":"12021dd3e1b46002218f72fad0f23dee32b1d2cc","user":{"login":"xiachufang","id":990080,"avatar_url":"https://avatars.githubusercontent.com/u/990080?v=3","gravatar_id":"","url":"https://api.github.com/users/xiachufang","html_url":"https://github.com/xiachufang","followers_url":"https://api.github.com/users/xiachufang/followers","following_url":"https://api.github.com/users/xiachufang/following{/other_user}","gists_url":"https://api.github.com/users/xiachufang/gists{/gist_id}","starred_url":"https://api.github.com/users/xiachufang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xiachufang/subscriptions","organizations_url":"https://api.github.com/users/xiachufang/orgs","repos_url":"https://api.github.com/users/xiachufang/repos","events_url":"https://api.github.com/users/xiachufang/events{/privacy}","received_events_url":"https://api.github.com/users/xiachufang/received_events","type":"Organization","site_admin":false},"repo":{"id":63569541,"name":"bandit-client","full_name":"xiachufang/bandit-client","owner":{"login":"xiachufang","id":990080,"avatar_url":"https://avatars.githubusercontent.com/u/990080?v=3","gravatar_id":"","url":"https://api.github.com/users/xiachufang","html_url":"https://github.com/xiachufang","followers_url":"https://api.github.com/users/xiachufang/followers","following_url":"https://api.github.com/users/xiachufang/following{/other_user}","gists_url":"https://api.github.com/users/xiachufang/gists{/gist_id}","starred_url":"https://api.github.com/users/xiachufang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xiachufang/subscriptions","organizations_url":"https://api.github.com/users/xiachufang/orgs","repos_url":"https://api.github.com/users/xiachufang/repos","events_url":"https://api.github.com/users/xiachufang/events{/privacy}","received_events_url":"https://api.github.com/users/xiachufang/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/xiachufang/bandit-client","description":null,"fork":false,"url":"https://api.github.com/repos/xiachufang/bandit-client","forks_url":"https://api.github.com/repos/xiachufang/bandit-client/forks","keys_url":"https://api.github.com/repos/xiachufang/bandit-client/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xiachufang/bandit-client/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xiachufang/bandit-client/teams","hooks_url":"https://api.github.com/repos/xiachufang/bandit-client/hooks","issue_events_url":"https://api.github.com/repos/xiachufang/bandit-client/issues/events{/number}","events_url":"https://api.github.com/repos/xiachufang/bandit-client/events","assignees_url":"https://api.github.com/repos/xiachufang/bandit-client/assignees{/user}","branches_url":"https://api.github.com/repos/xiachufang/bandit-client/branches{/branch}","tags_url":"https://api.github.com/repos/xiachufang/bandit-client/tags","blobs_url":"https://api.github.com/repos/xiachufang/bandit-client/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xiachufang/bandit-client/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xiachufang/bandit-client/git/refs{/sha}","trees_url":"https://api.github.com/repos/xiachufang/bandit-client/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xiachufang/bandit-client/statuses/{sha}","languages_url":"https://api.github.com/repos/xiachufang/bandit-client/languages","stargazers_url":"https://api.github.com/repos/xiachufang/bandit-client/stargazers","contributors_url":"https://api.github.com/repos/xiachufang/bandit-client/contributors","subscribers_url":"https://api.github.com/repos/xiachufang/bandit-client/subscribers","subscription_url":"https://api.github.com/repos/xiachufang/bandit-client/subscription","commits_url":"https://api.github.com/repos/xiachufang/bandit-client/commits{/sha}","git_commits_url":"https://api.github.com/repos/xiachufang/bandit-client/git/commits{/sha}","comments_url":"https://api.github.com/repos/xiachufang/bandit-client/comments{/number}","issue_comment_url":"https://api.github.com/repos/xiachufang/bandit-client/issues/comments{/number}","contents_url":"https://api.github.com/repos/xiachufang/bandit-client/contents/{+path}","compare_url":"https://api.github.com/repos/xiachufang/bandit-client/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xiachufang/bandit-client/merges","archive_url":"https://api.github.com/repos/xiachufang/bandit-client/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xiachufang/bandit-client/downloads","issues_url":"https://api.github.com/repos/xiachufang/bandit-client/issues{/number}","pulls_url":"https://api.github.com/repos/xiachufang/bandit-client/pulls{/number}","milestones_url":"https://api.github.com/repos/xiachufang/bandit-client/milestones{/number}","notifications_url":"https://api.github.com/repos/xiachufang/bandit-client/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xiachufang/bandit-client/labels{/name}","releases_url":"https://api.github.com/repos/xiachufang/bandit-client/releases{/id}","deployments_url":"https://api.github.com/repos/xiachufang/bandit-client/deployments","created_at":"2016-07-18T04:11:43Z","updated_at":"2016-08-09T02:22:01Z","pushed_at":"2016-08-12T03:10:47Z","git_url":"git://github.com/xiachufang/bandit-client.git","ssh_url":"git@github.com:xiachufang/bandit-client.git","clone_url":"https://github.com/xiachufang/bandit-client.git","svn_url":"https://github.com/xiachufang/bandit-client","homepage":null,"size":2,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":0,"forks":2,"open_issues":0,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/xiachufang/bandit-client/pulls/1"},"html":{"href":"https://github.com/xiachufang/bandit-client/pull/1"},"issue":{"href":"https://api.github.com/repos/xiachufang/bandit-client/issues/1"},"comments":{"href":"https://api.github.com/repos/xiachufang/bandit-client/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/xiachufang/bandit-client/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/xiachufang/bandit-client/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/xiachufang/bandit-client/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/xiachufang/bandit-client/statuses/0232392aec36054d21975001da6f9e14d6110e94"}}}}
{"actor":{"display_login":"yangyangxcf"}}