Python中如何实现人人网信息备份工具,敬请指教

前阵子人人网又冒了个热点,在热点事件前就考虑是不是把自己的人人信息备份下来。找了一圈,之前的各个备份工具在 2017 年人人登录机制改变后就都不能用了。参考前辈们的经验,写了这么一个工具:

https://github.com/whusnoopy/renrenBackup

目前可以

  1. 邮箱密码登录
  2. 抓取自己的 状态、留言板、相册、日志 及对应的评论和点赞信息
  3. 抓取指定用户,被当前登录用户可见的上述内容
  4. 用 Flask 展示抓取的信息

  1. 头像、照片都抓到本地了,但是可能有因为人人的原因导致原图不存在的情况
  2. 原文评论和点赞评论都抓了,但有遗漏多半是人人自己的锅,登录到官方网页版都看不到
  3. 点赞数是对的,但只能显示最近 8 个点赞的人,也是人人接口的锅,官方网页版也只显示 8 个人

还打算做的工作

  1. 纯静态输出(即脱离 Flask 查看,方便抓取后导给没有 Python 环境的其他人看)
  2. 对抓挂了的图的补救抓取(对应上面注 1 )
  3. RESTful + Vue.js 纯动态输出(自我学习玩)

Python中如何实现人人网信息备份工具,敬请指教

31 回复

赞一下~ 这是有用的东西, 比什么知乎爬虫高到不知道哪里去了~


要实现人人网信息备份工具,核心是模拟登录后爬取个人数据。这里提供一个基础框架:

import requests
import json
import time
from bs4 import BeautifulSoup

class RenrenBackup:
    def __init__(self):
        self.session = requests.Session()
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
        
    def login(self, email, password):
        """模拟登录人人网"""
        login_url = 'http://www.renren.com/ajaxLogin/login'
        login_data = {
            'email': email,
            'password': password,
            'icode': '',
            'origURL': 'http://www.renren.com/home',
            'domain': 'renren.com',
            'key_id': 1,
            'captcha_type': 'web_login'
        }
        
        response = self.session.post(login_url, data=login_data, headers=self.headers)
        if response.json().get('code'):
            print("登录成功")
            return True
        print("登录失败")
        return False
    
    def get_blog_list(self, user_id, page=1):
        """获取日志列表"""
        blog_url = f'http://blog.renren.com/blog/{user_id}/blogs'
        params = {'page': page}
        
        response = self.session.get(blog_url, params=params, headers=self.headers)
        soup = BeautifulSoup(response.text, 'html.parser')
        
        blogs = []
        for item in soup.select('.blog-list li'):
            title_elem = item.select_one('.title a')
            if title_elem:
                blog = {
                    'title': title_elem.text.strip(),
                    'link': title_elem['href'],
                    'time': item.select_one('.time').text.strip() if item.select_one('.time') else ''
                }
                blogs.append(blog)
        return blogs
    
    def get_album_list(self, user_id):
        """获取相册列表"""
        album_url = f'http://photo.renren.com/photo/{user_id}/album-list'
        response = self.session.get(album_url, headers=self.headers)
        
        # 解析相册数据(实际需要分析页面结构)
        # 这里只是示例框架
        return []
    
    def backup_all(self, email, password, user_id):
        """执行完整备份"""
        if not self.login(email, password):
            return
        
        # 备份日志
        print("开始备份日志...")
        all_blogs = []
        page = 1
        while True:
            blogs = self.get_blog_list(user_id, page)
            if not blogs:
                break
            all_blogs.extend(blogs)
            print(f"已获取第{page}页日志,共{len(blogs)}篇")
            page += 1
            time.sleep(1)  # 礼貌性延迟
        
        # 保存数据
        with open(f'renren_backup_{user_id}.json', 'w', encoding='utf-8') as f:
            json.dump({
                'blogs': all_blogs,
                'backup_time': time.strftime('%Y-%m-%d %H:%M:%S')
            }, f, ensure_ascii=False, indent=2)
        
        print(f"备份完成!共备份{len(all_blogs)}篇日志")

# 使用示例
if __name__ == '__main__':
    backup = RenrenBackup()
    # 替换为你的账号信息
    backup.backup_all('your_email@example.com', 'your_password', 'your_user_id')

关键点说明:

  1. 登录部分需要处理人人网的验证机制(可能需要验证码)
  2. 数据爬取要遵守robots.txt和网站条款
  3. 添加适当的请求延迟避免被封IP
  4. 可以扩展备份相册、状态、留言等功能

注意:人人网的反爬机制可能较严,实际使用时可能需要处理动态加载、加密参数等问题。

总结:核心是模拟登录后解析页面数据。

感谢 已备份

不错不错

活在我的记忆中

我以前按最近来访爬,爬了大概几万人

谢谢提醒,已停用

看起来不错,多谢分享

不错,我把它改一下

非常实用,已备份,送上感谢~

人人网好久不用了

进入主页就是一个妹子直播,还开着声音 现在人人网都这样了。。。

有人人的时候交往女生真是很容易啊

今天看到新闻,人人网的社交资产已经被陈一舟卖掉了,真庆幸自己先留了个后手

File “fetch.py”, line 5, in <module>
from playhouse.shortcuts import model_to_dict
ImportError: No module named playhouse.shortcuts

环境都装好了么?这个应该是 sqlite 库里的

非常实用,感谢楼主!

感谢大佬 非常棒的工具 已 Star

提两点意见:
1、浏览器中显示时支持左右方向键自动切换图片,这个比一个个点按钮体验要好很多
2、当前显示大图的时候似乎是按照 Actual Size 模式显示的,能否做成 Fit 模式显示,这样不用滚轮上下滚了。用户查看原图的话可以考虑双击或者放大镜工具。

再次感谢🙏

麻烦直接在 GitHub 项目下提 issue 吧,issue 不仅仅是问题,也可以是建议,这样有助于统一管理,如果有其他人能做,也可以看到 issue 后提 Pull Request (或者你有空的话也可以把这两个功能做掉发个 PR 来)

展示大图对宽高比过高的图片现在也加了最大高度限制,通过点击图片查看原图(可能会影响习惯了点图是看下一张操作),详见 https://github.com/whusnoopy/renrenBackup/issues/39

感谢 键盘快捷键现在已经很好用了 但是图片显示还是有的问题 每次都要上下拖动滚动条才能看全图片
另外请教下如何按用户名 /相册名称层级导出原始图片 方便用其他软件查看 谢谢🙏

看全图片这个可能还要再考虑下屏幕大小的适配优化,我开发调试是在 1920x1080 或 2560x1440 的分辨率下弄的,对更低分辨率或开了高 DPI 的是不太友好(捂脸

按用户名和相册名称导出原始图片,这个可以参考下 export.py 下的 export_albums 这个方法,就是导出的时候别渲染页面,直接新建文件夹拷贝图片就好

可以按照长宽中取 max 按照一定的比例缩放就行了
另外更新之后的版本似乎经常出现验证码的问题 而且验证码按照弹出的图片输入四个汉字总是通不过

get icode image, output to ./static/icode.jpg
Input text on Captcha icode image

就是这个缩放尺度把握不好,而且还有外部容器和内部图片的比例问题,前端设计还是见仁见智并且各种坑

验证码的问题,建议换个 IP 后把之前的登录信息清掉后再试,这个是触发安全阈值的问题,如果你的号在不同的地方登录或同一个 IP 不停的登不同的号,容易触发验证码,这个和代码版本没有关系

老哥 GitHub 上最新 pull 的代码有点问题 希望检查下😄

问题是什么。。。没看到 issue 这里也没有任何有效信息,猜猜我是谁么

抱歉 我没有说清楚
>>> python manage.py fetch -e mobile -p ‘pwd’ -u id_num -s -g -a -b -r
最后报错的部分结果为:
fetched 8 albums
prepare to fetch blogs
start crawl blog list page 0
Traceback (most recent call last):
File “manage.py”, line 116, in <module>
manager.run()
File “/usr/local/anaconda3/lib/python3.6/site-packages/flask_script/init.py”, line 417, in run
result = self.handle(argv[0], argv[1:])
File “/usr/local/anaconda3/lib/python3.6/site-packages/flask_script/init.py”, line 386, in handle
res = handle(*args, **config)
File “/usr/local/anaconda3/lib/python3.6/site-packages/flask_script/commands.py”, line 216, in call
return self.run(*args, **kwargs)
File “manage.py”, line 41, in fetch
fetched = fetch_user(uid, fetch_status=status, fetch_gossip=gossip, fetch_album=album, fetch_blog=blog)
File “/Users/XXX/Code/Python/renrenBackup/fetch.py”, line 99, in fetch_user
fetch_blog(uid)
File “/Users/XXX/Code/Python/renrenBackup/fetch.py”, line 76, in fetch_blog
blog_count = crawl_blog.get_blogs(uid)
File “/Users/XXX/Code/Python/renrenBackup/crawl/blog.py”, line 83, in get_blogs
total = load_blog_list(cur_page, uid)
File “/Users/XXX/Code/Python/renrenBackup/crawl/blog.py”, line 26, in load_blog_list
r = crawler.get_json(config.BLOG_LIST_URL.format(uid=uid), {‘curpage’: page})
File “/Users/XXX/Code/Python/renrenBackup/crawl/crawler.py”, line 123, in get_json
r = json.loads(resp.text.replace(’,}’, ‘}’))
File “/usr/local/anaconda3/lib/python3.6/json/init.py”, line 354, in loads
return _default_decoder.decode(s)
File “/usr/local/anaconda3/lib/python3.6/json/decoder.py”, line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File “/usr/local/anaconda3/lib/python3.6/json/decoder.py”, line 357, in raw_decode
raise JSONDecodeError(“Expecting value”, s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

这不是最新的代码更新带来的问题,而是人人网 Web 端的 blog 页面全挂导致的解析问题,在人人网自己解决这个问题前,暂时没有办法处理,建议跳过 -b 参数抓取 blog。这个在项目介绍文档一开始就有更新说明 https://github.com/whusnoopy/renrenBackup#%E4%BA%BA%E4%BA%BA%E7%BD%91%E4%BF%A1%E6%81%AF%E5%A4%87%E4%BB%BD%E5%B7%A5%E5%85%B7

有人提议可以用网页手机版来抓取,但是网页手机版的 blog 输出里,排版格式基本全挂,且不一定能输出全文,还有登陆安全问题(非 HTTPS,授权走明文参数),所以只能等待

另:遇到问题先看 Issue 列表也是个好习惯,可能你遇到的问题已经有其他人提出过了,如果没有,也在 Issue 里提出会更有助于他人了解问题

好的好的 感谢开发者👍

回到顶部