博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[译] 我是如何使用 Python 在 Medium 上找到并关注有趣的人
阅读量:6411 次
发布时间:2019-06-23

本文共 7072 字,大约阅读时间需要 23 分钟。

  • 原文地址:
  • 原文作者:
  • 译文出自:
  • 本文永久链接:
  • 译者:
  • 校对者:

图片来源:

Medium 上有大量的内容、用户和不计其数的帖子。当你试图寻找有趣的用户来关注时,你会发现自己不知所措。

我对于有趣的用户的定义是来自你的社交网络,保持活跃状态并经常在 Medium 社区发表高质量评论的用户。

我查看了我关注的用户的最新的帖子来看看是谁在回复他们。我认为如果他们回复了我关注的用户,这就说明他们可能和我志趣相投。

这个过程很繁琐,这就让我想起了我上次实习期间学到的最有价值的一课:

任何繁琐的任务都能够并且应该是自动化完成的。

我想要我的自动化程序能够做下面的事情:

  1. 从我的关注中获取所有的用户
  2. 从每一个用户中获取最新的帖子
  3. 获取每一个帖子的所有评论
  4. 筛选出30天以前的回复
  5. 筛选出少于最小推荐数的回复
  6. 获取每个回复的作者的用户名

让我们开始吧

我首先看了看 ,却发现它很有限。它给我提供的功能太少了。通过它,我只能获取关于我自己的账号信息,而不能获取其他用户的信息。

最重要的是,Medium's API 的最后一次更新是一年多前,最近也没有要开发的迹象。

我意识到我只能依靠 HTTP 请求来获取我的数据,所以我开始使用我的 。

第一个目标是获取我的关注列表。

我打开我的开发者工具并进入 Network 选项卡。我过滤了除了 之外的所有内容以查看 Medium 是从什么地方来获取我的关注的。我刷新了我的个人资料页面,但是什么有趣的事情都没发生。

如果我点击我的个人资料上的关注按钮怎么样?成功啦!

我找到用户关注列表的链接。

在这个链接中,我发现了一个非常大的 响应。它是一个格式很好的 JSON,除了在响应开头的一串字符:])}while(1);</x>

我写了一个函数整理了格式并把 JSON 转换成一个 Python 字典。

import jsondef clean_json_response(response):    return json.loads(response.text.split('])}while(1);')[1])复制代码

我已经找到了一个入口点,让我们开始编写代码吧。

从我的关注列表中获取所有用户

为了查询端点,我需要我的用户 ID(尽管我早就知道啦,这样做是出于教育目的)。

我在寻找获取用户 ID 的方法时可以通过添加 ?format=json 给 Medium 的 URL 地址来获取这个网页的 JSON 响应。我在我的个人主页上试了试。

看看,这就是我的用户 ID。

])}while(1);{
"success":true,"payload":{
"user":{
"userId":"d540942266d0","name":"Radu Raicea","username":"Radu_Raicea",...复制代码

我写了一函数从给出的用户名中提取用户 ID 。同样,我使用了 clean_json_response 函数来去除响应开头的不想要的字符串。

我还定义了一个叫 MEDIUM 的常量,它用来存储所有 Medium 的 URL 地址都包含的字符串。

import requestsMEDIUM = 'https://medium.com'def get_user_id(username):    print('Retrieving user ID...')    url = MEDIUM + '/@' + username + '?format=json'    response = requests.get(url)    response_dict = clean_json_response(response)    return response_dict['payload']['user']['userId']复制代码

通过用户 ID ,我查询了 /_/api/users/<user_id>/following 端点,从我的关注列表里获取了用户名列表。

当我在开发者工具中做这时,我注意到 JSON 响应只有八个用户名。很奇怪!

当我点击 “Show more people”,我找到了缺少的用户名。原来 Medium 使用的方式来展示关注列表。

Medium 使用分页的方式来展示关注列表。

分页通过指定 limit(每页元素)和 to(下一页的第一个元素)来工作,我必须找到一种方式来获取下一页的 ID。

在从 /_/api/users/<user_id>/following 获取的 JSON 响应的尾部,我看到了一个有趣的 JSON 键值对。

..."paging":{"path":"/_/api/users/d540942266d0/followers","next":{"limit":8,"to":"49260b62a26c"}}},"v":3,"b":"31039-15ed0e5"}复制代码

到了这一步,很容易就能写出一个循环从我的关注列表里面获取所有的用户名。

def get_list_of_followings(user_id):    print('Retrieving users from Followings...')        next_id = False    followings = []    while True:        if next_id:            # 如果这不是关注列表的第一页            url = MEDIUM + '/_/api/users/' + user_id                  + '/following?limit=8&to=' + next_id        else:            # 如果这是关注列表的第一页            url = MEDIUM + '/_/api/users/' + user_id + '/following'        response = requests.get(url)        response_dict = clean_json_response(response)        payload = response_dict['payload']        for user in payload['value']:            followings.append(user['username'])        try:            # 如果找不到 "to" 键,我们就到达了列表末尾,            # 并且异常将会抛出。            next_id = payload['paging']['next']['to']        except:            break    return followings复制代码

获取每个用户最新的帖子

我得到了我关注的用户列表之后,我就想获取他们最新的帖子。我可以通过发送这个请求 [https://medium.com/@<username>/latest?format=json](https://medium.com/@username/latest?format=json) 来实现这个功能。

于是我写了一个函数,这个函数的参数是用户名列表,然后返回一个包含输入进来的所有用户最新发表的帖子 ID 的 Python 列表。

def get_list_of_latest_posts_ids(usernames):    print('Retrieving the latest posts...')    post_ids = []    for username in usernames:        url = MEDIUM + '/@' + username + '/latest?format=json'        response = requests.get(url)        response_dict = clean_json_response(response)        try:            posts = response_dict['payload']['references']['Post']        except:            posts = []        if posts:            for key in posts.keys():                post_ids.append(posts[key]['id'])    return post_ids复制代码

获取每个帖子的所有评论

有了帖子的列表,我通过 https://medium.com/_/api/posts/<post_id>/responses 提取了所有的评论。

这个函数参数是帖子 ID Python 列表然后返回评论的Python列表。

def get_post_responses(posts):    print('Retrieving the post responses...')    responses = []    for post in posts:        url = MEDIUM + '/_/api/posts/' + post + '/responses'        response = requests.get(url)        response_dict = clean_json_response(response)        responses += response_dict['payload']['value']    return responses复制代码

筛选这些评论

一开始,我希望评论达到点赞的最小值。但是我意识到这可能并不能很好的表达出社区对于评论的赞赏程度,因为一个用户可以对同一条评论进行多次点赞。

相反,我使用推荐数来进行筛选。推荐数和点赞数差不多,但它不能多次推荐。

我希望这个最小值是可以动态调整的。所以我传递了名为 recommend_min 的变量。

下面的函数的参数是每一条评论和 recommend_min 变量。它用来检查评论的推荐数是否到达最小值。

def check_if_high_recommends(response, recommend_min):    if response['virtuals']['recommends'] >= recommend_min:        return True复制代码

我还希望得到最近的评论。因此我通过这个函数过滤掉超过 30 天的评论。

from datetime import datetime, timedeltadef check_if_recent(response):    limit_date = datetime.now() - timedelta(days=30)    creation_epoch_time = response['createdAt'] / 1000    creation_date = datetime.fromtimestamp(creation_epoch_time)    if creation_date >= limit_date:        return True复制代码

获取评论作者的用户名

在完成评论的筛选工作之后,我使用下面的函数来抓取所有作者的用户 ID。

def get_user_ids_from_responses(responses, recommend_min):    print('Retrieving user IDs from the responses...')    user_ids = []    for response in responses:        recent = check_if_recent(response)        high = check_if_high_recommends(response, recommend_min)        if recent and high:            user_ids.append(response['creatorId'])    return user_ids复制代码

当你试图访问某个用户的个人资料时,你会发现用户 ID 是没用的。这时我写了一个函数通过查询 /_/api/users/<user_id> 端点来获取用户名。

def get_usernames(user_ids):    print('Retrieving usernames of interesting users...')    usernames = []    for user_id in user_ids:        url = MEDIUM + '/_/api/users/' + user_id        response = requests.get(url)        response_dict = clean_json_response(response)        payload = response_dict['payload']        usernames.append(payload['value']['username'])    return usernames复制代码

把所以函数组合起来

在完成所有函数之后,我创建了一个来获取我的推荐用户列表。

def get_interesting_users(username, recommend_min):    print('Looking for interesting users for %s...' % username)    user_id = get_user_id(username)    usernames = get_list_of_followings(user_id)    posts = get_list_of_latest_posts_ids(usernames)    responses = get_post_responses(posts)    users = get_user_ids_from_responses(responses, recommend_min)    return get_usernames(users)复制代码

这个脚本程序终于完成啦!为了测试这个程序,你必须调用这个管道。

interesting_users = get_interesting_users('Radu_Raicea', 10)print(interesting_users)复制代码

图片来源:

最后,我添加了一个选项,可以把结果和时间戳存储在一个 CSV 文件里面。

import csvdef list_to_csv(interesting_users_list):    with open('recommended_users.csv', 'a') as file:        writer = csv.writer(file)        now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')        interesting_users_list.insert(0, now)                writer.writerow(interesting_users_list)        interesting_users = get_interesting_users('Radu_Raicea', 10)list_to_csv(interesting_users)复制代码

关于这个项目的源文件可以在。

如果你还不会 Python,阅读 的 Python 教程:。

如果你对其他让用户感兴趣的标准有建议,请在下面留言!

总结···

  • 我编写一个适用于 Medium 的 。
  • 这个脚本返回一个用户列表,里面的用户都是活跃的且在你的关注的用户的最新帖子下面发表过有趣的评论
  • 你可以从列表里取出用户,用他的用户名而不是你的来运行这个脚本。

点击我的关于开源许可的以及如何把它们添加到你的项目中!

更多更新,请关注我的 。

是一个翻译优质互联网技术文章的社区,文章来源为 上的英文分享文章。内容覆盖 、、、、、、、等领域,想要查看更多优质译文请持续关注 、、。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。

转载地址:http://ykkra.baihongyu.com/

你可能感兴趣的文章
dd命令使用详解
查看>>
centos7 设置开机启动服务
查看>>
【Java基础】序列化与反序列化深入分析
查看>>
浏览器跨域问题(jsonp)——jsonp详解
查看>>
Spring 注解总结
查看>>
4K加速普及,8K近在咫尺,下一个是?
查看>>
Application security
查看>>
主键生成策略
查看>>
django admin中保存添加的数据提示need string or buffer, int found
查看>>
Autofac.Integration.Mvc分析
查看>>
[Spring框架]Spring开发实例: XML+注解.
查看>>
java.lang.NoClassDefFoundError: javax/transaction/Synchronization
查看>>
黑客与画家——读后感
查看>>
实参时丢弃了类型 discards qualifiers discards qualifiers问题
查看>>
bzoj-2115 Xor
查看>>
gridcontrol复选框功能实现(超具体)
查看>>
Java面试题集(二)
查看>>
C#使用UUID生成ID
查看>>
图像处理就在身边
查看>>
Java-Maven(八):IDEA使用本地maven,并配置远程中央仓库
查看>>