前段时间玩「信长之野望·新生」比较上头,特别是开局时候的地图我很喜欢。
各种大名、城池、武将等数据摆放在那里,给赛博斗蛐蛐增添了无尽遐想。所以就有了这样一个念头,把我掘金中关注的朋友一些数值获取到,然后通过地图可视化的方式写一个群雄割据图。
完成这个项目后,我计划将其开源到Github。至于为什么要这么做?
"Just for fun" :创建一个数字世界,像古代英雄争霸割据一样类比社区活跃度,顺便给自己点账号运营动力与趣味性,毕竟今年给自己立了个 Flag:juejin.cn/post/733168...
一、拆解逻辑
首先,核心逻辑经过拆分,比较清晰:拿到数据,实现地图容器,数据映射填入,每天定时更新。
其次,可能需要再锦上添花,实现一些设定逻辑,比如:
- 掘力值(土地面积)
- 关注数(兵力值)
- 名称写个随机颜色映射逻辑(势力颜色)
- 从评论区拿点有趣点子 ...
二、数据获取
今天是第一篇,所以只基于页面的数据获取开展讨论。
如果我只关注了 5 个人,那其实手动维护数据都可以。
每天点击你主页里,把相关数据 CV 下来更新到数据表里,网站重新部署一下。
但哥们好歹是个工程师,实现方式就别这么 Low 了,况且我本身关注的人也很多,这工作能自动化最好。 以我个人主页为例,需要获取的数据有两类:
- 用户基础数据:掘力值、关注数、被关注数 ...
- 关注用户列表:关注了哪些人,这个列表是个动态的
01 | 用户基础数据
用户基础数据相对是比较好获取的,傻瓜一点的方式就是直接抓 html 页面元素值即可:
i. 开发思路
- 创建一个 requests 会话
- 发起 GET 请求,获取目标网页的内容
- 使用 BeautifulSoup 解析获取到的 HTML
- 通过 CSS 选择器找到目标元素,提取文本内容
- 将数字列表转换为字符串格式并打印
ii. 代码实现
python
import requests
from bs4 import BeautifulSoup
session = requests.Session()
# 获取关注和关注者数量
def get_followers(url):
response = session.get(url)
soup = BeautifulSoup(response.text, "html.parser")
follow_items = soup.find_all("a", {"class": "follow-item"})
following = []
followers = []
for follow_item_index, follow_item in enumerate(follow_items):
item_count = int(
follow_item.find("div", {"class": "item-count"}).get_text().strip()
)
if follow_item_index % 2 == 0:
following.append(item_count)
else:
followers.append(item_count)
following_str = ", ".join(map(str, following))
followers_str = ", ".join(map(str, followers))
return following_str, followers_str
# 获取基础数据
def get_baseData(url):
response = session.get(url)
soup = BeautifulSoup(response.text, "html.parser")
baseBlock = soup.find("div", {"class": "block-body"})
counts = baseBlock.find_all("span", {"class": "count"})
data = {}
if len(counts) >= 3:
data["likes"] = counts[0].get_text().strip()
data["reads"] = counts[1].get_text().strip()
data["jueli"] = counts[2].get_text().strip()
return data
url = "https://juejin.cn/user/1591748568038823" # 请替换为你关注的作者的页面 URL
following_str, followers_str = get_followers(url)
print(f"following: {following_str}")
print(f"followers: {followers_str}")
baseData = get_baseData(url)
print(baseData)
02 | 关注列表数据
这个难度稍微高一点,因为掘金关注列表有滚动加载,所以需要模拟用户翻页的行为才能获取到全部关注。用 Network 查接口也行,但字段太多不想查了。
有知道实现方式的老哥欢迎评论区分享,大家一起讨论下。
i. 开发思路
- 用户输入的 URL
- 使用 selenium 库启动 Chrome 浏览器并打开指定的 URL
- 通过滚动和检查页面高度变化来加载所有关注用户
- 使用 CSS 选择器定位并提取关注用户的信息
- 将提取到的用户信息保存到新文件中
ii. 代码实现
python
import argparse
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
# 获取用户关注列表(处理加载与翻页)
def get_my_following(url):
# 设置WebDriver路径
webdriver_service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=webdriver_service)
driver.get(url)
# 滚动页面直到没有新的用户加载
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2) # 等待新的用户加载
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height: # 如果没有新的用户加载,停止滚动
break
last_height = new_height
following_users = driver.find_elements(By.CSS_SELECTOR, "ul.tag-list a.username")
following_list = [user.text for user in following_users]
driver.quit()
return following_list
# 新建or覆盖,保存用户关注列表
def save_following_to_file(following_list, filename):
with open(filename, "w") as f:
for user in following_list:
f.write(user + "\n")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Get the list of users you are following on Juejin."
)
parser.add_argument("url", help="The URL of your following list on Juejin.")
args = parser.parse_args()
following_list = get_my_following(args.url)
length = len(following_list)
print("关注用户数:", length)
# 保存关注的用户到文件
save_following_to_file(following_list, "following.txt")
三、功能封装
python 依赖和环境一个个安装挺麻烦,所以我这里对模块使用做了一层封装。感兴趣的朋友你 pull 到本地就能用。
项目地址:github.com/Trade-Offf/...
执行方法:
- 添加脚本权限:
chmod +x install_and_run.sh
clone 仓库后只用执行一次,脚本有了执行权限,你就可以直接运行它,无需再次使用 chmod 命令。
- 导出关注列表:
./install_and_run.sh (URL-待替换)
其中 URL 是需要导出的关注页,如:https://juejin.cn/user/1591748568038823/following
四、可视化容器(TODO)
下一节实现地图容器,看了这个原神哥的文章,大受启发: