爬虫实战: 抓取唧唧堂网站公开的用户信息

原创
2020/02/13 20:12
阅读数 0

大家学习可以,请慎用爬虫。爬的太猛容易瘫痪人家的服务器,记得time.sleep数值大一些,慢一些。珍爱待爬网站,切记切记!!

很久没写爬虫了,今天写个学术性网站的爬虫教程。通过抓取这个网站用户的 学校、学院和文献笔记等信息,我们能对学术圈做一些简单的分析,比如 找到哪些同仁比较勤奋,笔耕不辍(阅读文献并做阅读文档)。 😑反正我比较懒,唧唧堂中我还没有分享一篇阅读笔记😆

待爬网站介绍:

唧唧堂:http://www.jijitang.com/profile

唧唧堂是一个从2012年开始运营的研究人UGC社区,社区用户包括高校的学生、学者、行业研究员等,经过5年的积累,社区内已经有6.5万高学历、多背景学科的研究人。

唧唧堂创始人 宣悠悠 拥有美国圣塔克拉拉大学信息系统硕士学位,曾在硅谷工作和学习三年,具有超过6年的IT和互联网工作经验;另一位联合创始人拥有武汉大学金融硕士和学士学位,曾任资产管理公司研究院、金融IT上市公司互联网金融产品总监。

一、抓包分析

F12键打开开发者工具,使用开发者工具 Network面板XHR工具,刷新当前网页。我们发现 唧唧堂 网站的数据是 json格式数据

而且经过分析发现,当前页面中没有 下一页 这种按钮,只要我们向下滑动页面,就会不断有新内容出现,所以当前网址(页面)是 动态网页

json数据的爬虫编写起来很简单,因为主要的难点在于抓包分析,找到url规律。

所以我们盯着开发者 Network面板,多 向下滑动几次。得到一下两个面板截图。

我们发现每次获得的用户数据中 最后一个用户的 _id,是 下一个url中的一个参数

http://www.jijitang.com/profile/list?sort=recommend&last=2053&ltId=5b95f1f9845a7631727c6b14
http://www.jijitang.com/profile/list?sort=recommend&last=2043&ltId=5b8b9f092be304901ee15037
http://www.jijitang.com/profile/list?sort=recommend&last=2033&ltId=5b823a0efa4ae540215056f3

同时,url中有一个last参数,该参数递减,每个url的last参数比之前url减少10。

网址规律

url规律可以归纳为

http://www.jijitang.com/profile/list?sort=recommend&last={last}&ltId={lastid}

我们只需要变动 lastlastid 这两个参数就可以 获取唧唧堂用户信息

注意:

last参数最大为2053, 我们可以猜想该网站目前注册用户大概有 20530人(2053*10)

二、发起请求

在本文教程中我们使用 requests发起请求

为了方便理解,我们初识的url为 http://www.jijitang.com/profile/list?sort=recommend&last=2053&ltId=5b95f1f9845a7631727c6b14

从该url中提取出初识参数 lastidlast

lastid = '5b95f1f9845a7631727c6b14'
last = 2053
import requests
import csv


lastid = '5b95f1f9845a7631727c6b14'
last = 2053



base = 'http://www.jijitang.com/profile/list?sort=recommend&last={last}&ltId={lastid}'
url = base.format(last=last, lastid=lastid)
resp = requests.get(url)
resp.json()

运行结果

    [{'_id''5b93fcf3c2f15ecd73ddf5ca',
      'avatar''/img/user-avatar-default.jpg',
      'background''/img/user-background-default.jpg',
      'publications': [],
      'tags': [],
      'readLaters': [],
      'likes': [],
      'followCollectionCount'0,
      'followCollections': [],
      'followByCount'0,
      'followCount'0,
      'followBy': [],
      'follow': [],
      'role''user',
      'updateTime''2018-09-08T16:46:43.972Z',
      'createTime''2018-09-08T16:46:43.971Z',
      '__v'0,
      'experience''',
      '
field': 'Economics / Finance',
      '
institution': {'role': '博士生', 'institute': '对外经济贸易大学', 'dept': '国际商学院'},
      '
nickname': '朱郭一鸣',
      '
profile': '对外经济贸易大学会计学博士',
      '
rate': 2052,
      '
articleCount': 0,
      '
followed': False},
      。。。。
      。。。。
      。。。。

     {'
_id': '5b8b9f092be304901ee15037',
      '
avatar': '/img/user-avatar-default.jpg',
      '
publications': [],
      '
interests': ['国际商务,战略'],
      '
tags': [],
      '
readLaters': [],
      '
likes': [],
      '
followCollectionCount': 0,
      '
followCollections': ['583e4222b72db42c18dccddb',
       '
583e3ea0b72db42c18dcc2db'],
      '
followByCount': 0,
      '
followCount': 1,
      '
followBy': [],
      '
follow': ['545895f61bf722f2452cf081'],
      '
role': 'user',
      '
updateTime': '2018-09-02T08:27:53.809Z',
      '
createTime': '2018-09-02T08:27:53.809Z',
      '
__v': 2,
      '
experience': '',
      '
field': 'Social Sciences',
      '
institution': {'role': '硕士生', 'institute': '吉林大学', 'dept': '管理学院'},
      '
nickname': '独自挣扎的小白',
      '
profile': '',
      '
rate': 2043,
      '
articleCount': 0,
      '
followed': False}]

三、用户信息

为了让教程简洁,在教程中我们只收集:

  • 昵称nickname

  • 用户id

  • 简介profile

  • 学历role

  • 学校institute

  • 学院dept

import csv
import requests

#初识url参数
lastid = '5b95f1f9845a7631727c6b14'
last = 2053

#新建csv文件
csvf = open('user_data.csv''a+', encoding='gbk', newline='')
writer = csv.writer(csvf)
writer.writerow(('昵称''id''简介''学历''学校''学院'))

#发起请求
base = 'http://www.jijitang.com/profile/list?sort=recommend&last={last}&ltId={lastid}'
url = base.format(last=last, lastid=lastid)
resp = requests.get(url)
users = resp.json()

#保存
for user in users:
    nickname = user.get('nickname'#昵称
    profile = user.get('profile')   #简介
    role = user.get('institution').get('role'#学历
    institute = user.get('institution').get('institute'#所属学校
    dept = user.get('institution').get('dept'#所属学院
    userid = user.get('_id')
    #逐行写入并打印
    writer.writerow((nickname, userid, profile, role , institute, dept))
    print(nickname, userid, profile, role , institute, dept)

运行结果

    朱郭一鸣 5b93fcf3c2f15ecd73ddf5ca 对外经济贸易大学会计学博士 博士生 对外经济贸易大学 国际商学院
    瓜胖 5b94d4d0845a7631727c6b05  学生 南京工业大学 经济与管理学院
    .......
    .......
    volcano 5b8f2f25d89a20ab1ebb48d0 一个爱换头像的女同学。 研究生 北京体育大学 心理学院
    流浪飞沙 5b8d08d0d89a20ab1ebb48aa 一味想着死的事,一定是因为太过认真地活 硕士研究生 南京师范大学 心理学院
    独自挣扎的小白 5b8b9f092be304901ee15037  硕士生 吉林大学 管理学院

四、完整的爬虫

上面的爬虫是非常简单的,只是对  http://www.jijitang.com/profile/list?sort=recommend&last=2053&ltId=5b95f1f9845a7631727c6b14  十个用户的抓取和存储。 现在我们根据该初识url自动实现抓取,因为我们知道下一个url是根据上一个url对应的最后一个用户决定的。

这里我们定义 start_request函数,并且函数结尾 return start_request(writer, last, lastid) 实现递归抓取。

为了防止爬虫运行太快,给唧唧堂带来太大的压力,我们将sleep设置为1

import csv
import requests
import time


def start_request(writer, last, lastid, sleep=1):
    #发起请求
    base = 'http://www.jijitang.com/profile/list?sort=recommend&last={last}&ltId={lastid}'
    url = base.format(last=last, lastid=lastid)
    resp = requests.get(url)
    users = resp.json()

    #保存
    for user in users:
        nickname = user.get('nickname'#昵称
        userid = user.get('_id')        #用户id
        profile = user.get('profile')   #简介


        role = user.get('institution').get('role'#学历
        institute = user.get('institution').get('institute'#所属学校
        dept = user.get('institution').get('dept'#所属学院


        #逐行写入并打印
        writer.writerow((nickname, userid, profile, role , institute, dept))
        print(last, nickname, userid, profile, role , institute, dept)

    #最后一个用户的信息,
    #注意用户信息中的rate关键词对应着last参数
    #用户信息中的_id关键词对应着lastid参数
    last_user = users[-1]  
    last = last_user.get('rate')
    lastid = last_user.get('_id')

    #降低访问速度
    time.sleep(sleep) 

    #根据最后一个用户的last和lastid,实现对下一批用户信息的抓取(递归)
    return start_request(writer, last, lastid)



#初识url参数
lastid = '5b95f1f9845a7631727c6b14'
last = 2053

#新建csv文件
csvf = open('user_data.csv''a+', encoding='gbk', newline='')
writer = csv.writer(csvf)
writer.writerow(('昵称''id''简介''学历''学校''学院'))

#开始递归抓取
start_request(writer, last, lastid)

运行结果

    2053 朱郭一鸣 5b93fcf3c2f15ecd73ddf5ca 对外经济贸易大学会计学博士 博士生 对外经济贸易大学 国际商学院
    2053 瓜胖 5b94d4d0845a7631727c6b05  学生 南京工业大学 经济与管理学院
    2053 欧++ 5b9353a0845a7631727c6af4  博士 中国农业大学 经济管理学院
    2053 张丽丽 5b90515b2be304901ee1508b  教师 安徽工业经济学院 商贸学院
    2053 胡先生 5b90a46cd89a20ab1ebb48e8 量化投资爱好者! 副教授 复旦大学 经济学院
    2053 容容love 5b8f46152be304901ee1507b 心理学小白 学生 辽师 心理学院
    2053 ydt 5b8f376c2be304901ee15079 No pain,no gain! 博士生 北京体育大学 心理学院
    2053 volcano 5b8f2f25d89a20ab1ebb48d0 一个爱换头像的女同学。 研究生 北京体育大学 心理学院
    2053 流浪飞沙 5b8d08d0d89a20ab1ebb48aa 一味想着死的事,一定是因为太过认真地活 硕士研究生 南京师范大学 心理学院
    2053 独自挣扎的小白 5b8b9f092be304901ee15037  硕士生 吉林大学 管理学院
    2043 xxx 5b8b76472be304901ee15034 上半生得到的容易,是以浮浮浅浅,门门似懂非懂,半罐醋叮当作响,一无所长一无所成,好在身形尚可,心理康健。
    下半生还仍没到来,只盼兢兢业业,事事无愧于心,憋一口真气不散,半学处事半学佛法,止于经世济人,和济乡邻。 学生 山东大学 经济学院
    2043 李三省 5b8a0239d89a20ab1ebb488d 生活中的实用主义者,学术中的理想主义者。 博士,研究员 南京大学商学院 南京大学经济学院
    2043 琦琦不是奇奇 5b88a1fa2be304901ee14fc9 学术小白,努力追逐大神的脚步,一点一点提升自己。 博士生 东北师范大学 商学院
    2043 卡嚓 5b86bb842be304901ee14fbe  研究助理 暨南大学 华文学院
    2043 LINA 5b87b68e2be304901ee14fc4  博士 中科院 数学与系统科学研究院
    2043 Qian Cheng 5b8789162be304901ee14fc0  Student Zhejiang University School of Economics



    ---------------------------------------------------------------------------

    AttributeError                            Traceback (most recent call last)

    <ipython-input-9-522d2754e09a> in <module>()
         48 
         49 #开始递归抓取
    ---> 50 start_request(writer, last, lastid)


    <ipython-input-9-522d2754e09a> in start_request(writer, last, lastid, sleep)
         34 
         35     #根据最后一个用户的last和lastid,实现对下一批用户信息的抓取(递归)
    ---> 36     return start_request(writer, last, lastid)
         37 
         38 


    <ipython-input-9-522d2754e09a> in start_request(writer, last, lastid, sleep)
         16         userid = user.get('_id')        #用户id
         17         profile = user.get('profile')   #简介
    ---> 18         role = user.get('institution').get('role') #学历
         19         institute = user.get('institution').get('institute'#所属学校
         20         dept = user.get('institution').get('dept'#所属学院


    AttributeError: 'NoneType' object has no attribute 'get'

五、更健壮的爬虫

上面的代码还不够强壮,因为有的用户并不会公开 学历、学校、学院 信息, 所以遇到没有填写相关信息的用户,爬虫报错停止,为此我们将 role、institute、dept 这三个内容放在 try-except语句 中,增强爬虫的 鲁棒性 robust

import csv
import requests
import time


def start_request(writer, last, lastid, sleep=1):
    #发起请求
    base = 'http://www.jijitang.com/profile/list?sort=recommend&last={last}&ltId={lastid}'
    url = base.format(last=last, lastid=lastid)
    resp = requests.get(url)
    users = resp.json()

    #保存
    for user in users:
        nickname = user.get('nickname'#昵称
        userid = user.get('_id')        #用户id
        profile = user.get('profile')   #简介

        try:
            role = user.get('institution').get('role'#学历
            institute = user.get('institution').get('institute'#所属学校
            dept = user.get('institution').get('dept'#所属学院
        except:
            role = '无'
            institute = '无'
            dept = '无'

        #逐行写入并打印
        writer.writerow((nickname, userid, profile, role , institute, dept))
        print(last, nickname, userid, profile, role , institute, dept)

    #最后一个用户的信息,
    #注意用户信息中的rate关键词对应着last参数
    #用户信息中的_id关键词对应着lastid参数
    last_user = users[-1]  
    last = last_user.get('rate')
    lastid = last_user.get('_id')

    #降低访问速度
    time.sleep(sleep) 

    #根据最后一个用户的last和lastid,实现对下一批用户信息的抓取(递归)
    return start_request(writer, last, lastid)



#初识url参数
lastid = '5b95f1f9845a7631727c6b14'
last = 2053

#新建csv文件
csvf = open('user_data.csv''a+', encoding='gbk', newline='')
writer = csv.writer(csvf)
writer.writerow(('昵称''id''简介''学历''学校''学院'))

#开始递归抓取
start_request(writer, last, lastid)

运行结果

    2053 朱郭一鸣 5b93fcf3c2f15ecd73ddf5ca 对外经济贸易大学会计学博士 博士生 对外经济贸易大学 国际商学院
    2053 瓜胖 5b94d4d0845a7631727c6b05  学生 南京工业大学 经济与管理学院
    ....
    ....

    2043 李三省 5b8a0239d89a20ab1ebb488d 生活中的实用主义者,学术中的理想主义者。 博士,研究员 南京大学商学院 南京大学经济学院
   ....
   ....

    2023 Yang Wengui 5b76d6df89efe6124168651c  学生 长春理工大学 电子信息工程学院
   ....
   ....

    1983 一只break 5b3b531889efe61241685cb6 对世界拥有好奇心 学生 华中科技大学 经济学院
    1983 硌牙的小钢豆 5b399de4870fe9f74089eaf8  博士生 对外经济贸易大学 金融学院
    1983 陈亮 5b387f9289efe61241685c93 我是重庆大学经济与工商管理学院应用经济学博士生,研究方向为区域、空间、制度经济 博士生 重庆大学 经济与工商管理学院


往期文章

安装问题 error: command 'gcc' failed with exit status 1

大邓强力推荐-jupyter notebook使用小技巧       

10分钟理解深度学习中的~卷积~  

深度学习之 图解LSTM   

PyTorch实战: 使用卷积神经网络对照片进行分类  

Pytorch实战:使用RNN网络对姓名进行分类   

100G Python学习资料(免费下载) 

100G 文本分析语料资源(免费下载)    

typing库:让你的代码阅读者再也不用猜猜猜  

Seaborn官方教程中文教程(一)

数据清洗 常用正则表达式大全

PySimpleGUI: 开发自己第一个软件

深度特征合成:自动生成机器学习中的特征

Python 3.7中dataclass的终极指南(一) 

Python 3.7中dataclass的终极指南(二) 

15个最好的数据科学领域Python库    

使用Pandas更好的做数据科学

[计算消费者的偏好]推荐系统与协同过滤、奇异值分解

机器学习: 识别图片中的数字

应用PCA降维加速模型训练

如何从文本中提取特征信息?

使用sklearn做自然语言处理-1 

使用sklearn做自然语言处理-2

机器学习|八大步骤解决90%的NLP问题    

Python圈中的符号计算库-Sympy

Python中处理日期时间库的使用方法 

视频讲解】Scrapy递归抓取简书用户信息

美团商家信息采集神器 

用chardect库解决网页乱码问题 


本文分享自微信公众号 - 大邓和他的Python(DaDengAndHisPython)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部