Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
lzjun567 committed Apr 16, 2017
1 parent caaaea6 commit 9aa340d
Show file tree
Hide file tree
Showing 10 changed files with 286 additions and 21 deletions.
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

68 changes: 68 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## 项目简介

Zhihu API For Humans Based on Python3

## 前置条件

* Python3.x
* Requests2
* BeautifulSoup4

## 安装

```python
git@github.com:lzjun567/zhihu-api.git
cd zhihu-api
pip install -r requirement.txt
```

## API使用

### 获取用户信息: zhihu.user(id)

获取用户信息时,接收的参数可以是用户的主页地址 profile_url,也可以是用户的个性化名字 user_slug

```
>>> from zhihu import Zhihu
>>> zhihu = Zhihu()
>>> zhihu.user(profile_url="https://www.zhihu.com/people/xiaoxiaodouzi")
>>> zhihu.user(user_slug="xiaoxiaodouzi")
{'avatar_url_template': 'https://pic1.zhimg.com/v2-ca13758626bd7367febde704c66249ec_{size}.jpg', 'badge': [], 'name': '我是小号', 'headline': '程序员', 'gender': -1, 'user_type': 'people', 'is_advertiser': False, 'avatar_url': 'https://pic1.zhimg.com/v2-ca13758626bd7367febde704c66249ec_is.jpg', 'url': 'http://www.zhihu.com/api/v4/people/1da75b85900e00adb072e91c56fd9149', 'type': 'people', 'url_token': 'xiaoxiaodouzi', 'id': '1da75b85900e00adb072e91c56fd9149', 'is_org': False}
```

### 发私信: zhihu.send_message(id)

获取用户信息时,接收的参数可以是用户的主页地址 profile_url,也可以是用户的个性化名字 user_slug, 还可以是用户的id


```python
>>> zhihu.send_message("你好,问候1", profile_url="https://www.zhihu.com/people/xiaoxiaodouzi")
{'sender': {'avatar_url_template': 'https://pic3.zhimg.com/ca6bf4bb82d9cf152b618edcbda01606_{size}.jpg', 'badge': [], 'name': 'zhijun liu', 'is_advertiser': False, 'url': 'http://www.zhihu.com/api/v4/people/ba286d02fd9701a446d68ba85d0755c0', 'url_token': 'zhijun-liu', 'user_type': 'people', 'headline': '公众号:Python之禅', 'avatar_url': 'https://pic3.zhimg.com/ca6bf4bb82d9cf152b618edcbda01606_is.jpg', 'is_org': False, 'gender': 1, 'type': 'people', 'id': 'ba286d02fd9701a446d68ba85d0755c0'}, 'url': '', 'has_read': False, 'content': '你好,问候1', 'receiver': {'avatar_url_template': 'https://pic1.zhimg.com/v2-ca13758626bd7367febde704c66249ec_{size}.jpg', 'badge': [], 'name': '我是小号', 'is_advertiser': False, 'url': 'http://www.zhihu.com/api/v4/people/1da75b85900e00adb072e91c56fd9149', 'url_token': 'xiaoxiaodouzi', 'user_type': 'people', 'headline': '程序员', 'avatar_url': 'https://pic1.zhimg.com/v2-ca13758626bd7367febde704c66249ec_is.jpg', 'is_org': False, 'gender': -1, 'type': 'people', 'id': '1da75b85900e00adb072e91c56fd9149'}, 'created_time': 1492318772, 'type': 'message', 'id': '2143862420'}

>>> zhihu.send_message("你好,问候2", user_slug="xiaoxiaodouzi")
{'sender': {'avatar_url_template': 'https://pic3.zhimg.com/ca6bf4bb82d9cf152b618edcbda01606_{size}.jpg', 'name': 'zhijun liu', 'is_advertiser': False, 'url': 'http://www.zhihu.com/api/v4/people/ba286d02fd9701a446d68ba85d0755c0', 'badge': [], 'user_type': 'people', 'url_token': 'zhijun-liu', 'headline': '公众号:Python之禅', 'avatar_url': 'https://pic3.zhimg.com/ca6bf4bb82d9cf152b618edcbda01606_is.jpg', 'is_org': False, 'gender': 1, 'type': 'people', 'id': 'ba286d02fd9701a446d68ba85d0755c0'}, 'url': '', 'has_read': False, 'content': '你好,问候2', 'receiver': {'avatar_url_template': 'https://pic1.zhimg.com/v2-ca13758626bd7367febde704c66249ec_{size}.jpg', 'name': '我是小号', 'is_advertiser': False, 'url': 'http://www.zhihu.com/api/v4/people/1da75b85900e00adb072e91c56fd9149', 'badge': [], 'user_type': 'people', 'url_token': 'xiaoxiaodouzi', 'headline': '程序员', 'avatar_url': 'https://pic1.zhimg.com/v2-ca13758626bd7367febde704c66249ec_is.jpg', 'is_org': False, 'gender': -1, 'type': 'people', 'id': '1da75b85900e00adb072e91c56fd9149'}, 'created_time': 1492318780, 'type': 'message', 'id': '6343862420'}

>>> zhihu.send_message("你好,问候3", user_id="1da75b85900e00adb072e91c56fd9149")
{'sender': {'avatar_url_template': 'https://pic3.zhimg.com/ca6bf4bb82d9cf152b618edcbda01606_{size}.jpg', 'name': 'zhijun liu', 'is_advertiser': False, 'url': 'http://www.zhihu.com/api/v4/people/ba286d02fd9701a446d68ba85d0755c0', 'badge': [], 'user_type': 'people', 'url_token': 'zhijun-liu', 'headline': '公众号:Python之禅', 'avatar_url': 'https://pic3.zhimg.com/ca6bf4bb82d9cf152b618edcbda01606_is.jpg', 'is_org': False, 'gender': 1, 'type': 'people', 'id': 'ba286d02fd9701a446d68ba85d0755c0'}, 'url': '', 'has_read': False, 'content': '你好,问候3', 'receiver': {'avatar_url_template': 'https://pic1.zhimg.com/v2-ca13758626bd7367febde704c66249ec_{size}.jpg', 'name': '我是小号', 'is_advertiser': False, 'url': 'http://www.zhihu.com/api/v4/people/1da75b85900e00adb072e91c56fd9149', 'badge': [], 'user_type': 'people', 'url_token': 'xiaoxiaodouzi', 'headline': '程序员', 'avatar_url': 'https://pic1.zhimg.com/v2-ca13758626bd7367febde704c66249ec_is.jpg', 'is_org': False, 'gender': -1, 'type': 'people', 'id': '1da75b85900e00adb072e91c56fd9149'}, 'created_time': 1492318799, 'type': 'message', 'id': '3244862420'}
>>>
```

## TODO

* 关注
* 文章点赞
* ...

## 贡献者
欢迎 PR, 所有贡献者都将出现在这里

## 交流

![公众号](gongzhonghao.png)

![](weixingroup.jpeg)

2 changes: 2 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# encoding: utf-8
__author__ = 'liuzhijun'
Binary file added captcha.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gongzhonghao.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# encoding: utf-8
__author__ = 'liuzhijun'
import time
from zhihu import Zhihu

if __name__ == '__main__':
zhihu = Zhihu()
profile = zhihu.user(profile_url="https://www.zhihu.com/people/xiaoxiaodouzi")
time.sleep(1)
profile = zhihu.user(user_slug="xiaoxiaodouzi")
time.sleep(1)
_id = profile.get("id")
zhihu.send_message("你好,问候1", profile_url="https://www.zhihu.com/people/xiaoxiaodouzi")
time.sleep(1)
zhihu.send_message("你好,问候2", user_slug="xiaoxiaodouzi")
time.sleep(1)
zhihu.send_message("你好,问候3", user_id=_id)

2 changes: 2 additions & 0 deletions requirement.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
requests==2.13.0
beautifulsoup4==4.5.3
32 changes: 32 additions & 0 deletions url.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# encoding: utf-8

"""
通用URL类,知乎官方URL接口地址
"""


class URL(object):
# 登录
@staticmethod
def login():
return "https://www.zhihu.com/login/email"

# 私信
@staticmethod
def message():
return "https://www.zhihu.com/api/v4/messages"

# 验证码
@staticmethod
def captcha(timestamp):
return 'https://www.zhihu.com/captcha.gif?r={timestamp}&type=login'

# 首页
@staticmethod
def index():
return "https://www.zhihu.com"

# 用户信息
@staticmethod
def profile(url_token):
return "https://www.zhihu.com/api/v4/members/{url_token}".format(url_token=url_token)
Binary file added weixingroup.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
164 changes: 164 additions & 0 deletions zhihu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# encoding: utf-8
# !/usr/bin/env python

"""
知乎API
"""
import logging
import os
import re
import time
from http import cookiejar

import requests
from bs4 import BeautifulSoup
from url import URL

logging.basicConfig(level=logging.INFO)

# cookies 文件保存在当前用户目录,
# 下次程序重新启动时,直接加载cookie文件,无需再输入用户名和密码登录
cookie_filename = os.path.join(os.path.expanduser('~'), "cookies.txt")


def need_login(func):
"""
用户认证(判断用户是否已经登录的装饰器)
"""

def wrapper(self, *args, **kwargs):
success = True
if not os.path.exists(cookie_filename):
success = False
while not success:
email = input("请输入email:")
password = input("请输入密码:")
success = self.login(email, password)
if success:
result = func(self, *args, **kwargs)
return result

return wrapper


class Zhihu(object):
logger = logging.getLogger(__name__)

def __init__(self):
self._session = requests.session()
self._session.verify = False
self._session.headers = {"Host": "www.zhihu.com",
"Referer": "https://www.zhihu.com/",
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36'
' (KHTML, like Gecko) Chrome/56.0.2924.87',
}
self._session.cookies = cookiejar.LWPCookieJar(filename=cookie_filename)
try:
self._session.cookies.load(ignore_discard=True)
except:
pass

def _get_captcha(self):
t = str(int(time.time() * 1000))
r = self._session.get(URL.captcha(t))
with open('captcha.jpg', 'wb') as f:
f.write(r.content)
captcha = input("验证码:")
return captcha

def _get_xsrf(self):
response = self._session.get(URL.index())
soup = BeautifulSoup(response.content, "html.parser")
xsrf = soup.find('input', attrs={"name": "_xsrf"}).get("value")
return xsrf

def login(self, email, password):
"""
登录需要的验证码会保存在当前目录,需要用户自己识别,并输入
"""
request_body = {'email': email,
'password': password,
'_xsrf': self._get_xsrf(),
"captcha": self._get_captcha(),
'remember_me': 'true'}

response = self._session.post(URL.login(), data=request_body)
if response.ok:
data = response.json()
if data.get("r") == 0:
# 登录成功'
self._session.cookies.save()
self.logger.info("登录成功")
return True
else:
self.logger.info("登录失败, %s" % data.get("msg"))

else:
self.logger.error(response.content)
return False

@need_login
def send_message(self, content, user_id=None, profile_url=None, user_slug=None):
"""
给指定的用户发私信
:param content 私信内容
:param user_id 用户id
:param profile_url :用户主页地址
:param user_slug : 用户的个性域名
>>> send_message(profile_url = "https://www.zhihu.com/people/xiaoxiaodouzi")
>>> send_message(user_slug = "xiaoxiaodouzi")
>>> send_message(user_id = "1da75b85900e00adb072e91c56fd9149")
"""

if not any([user_id, profile_url, user_slug]):
raise Exception("至少指定一个关键字参数")

if not user_id and user_slug:
profile = self.user(user_slug)
user_id = profile.get("id")
elif not user_id and profile_url:
pattern = re.compile("https?://www.zhihu.com/people/([\w-]+)")
match = pattern.search(profile_url)
if match:
user_slug = match.group(1)
profile = self.user(user_slug)
user_id = profile.get("id")

data = {"type": "common", "content": content, "receiver_hash": user_id}
response = self._session.post(URL.message(), json=data)
data = response.json()
if data.get("error"):
self.logger.info("私信发送失败, %s" % data.get("error").get("message"))
else:
self.logger.info("发送成功")
return data

@need_login
def user(self, user_slug=None, profile_url=None):
"""
获取用户信息
:param user_slug : 用户的个性域名
:param profile_url: 用户主页地址
:return:dict
>>> user(profile_url = "https://www.zhihu.com/people/xiaoxiaodouzi")
>>> user(user_slug = "xiaoxiaodouzi")
"""

if not any([profile_url, user_slug]):
raise Exception("至少指定一个关键字参数")

if not user_slug and profile_url:

pattern = re.compile("https?://www.zhihu.com/people/([\w-]+)")
match = pattern.search(profile_url)
if match:
user_slug = match.group(1)
response = self._session.get(URL.profile(user_slug))
if response.ok:
return response.json()
else:
self.logger.error(u"获取用户信息失败, status code: %s" % response.status_code)

0 comments on commit 9aa340d

Please sign in to comment.