前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >左右用R右手Pyhon系列——趣直播课程抓取实战

左右用R右手Pyhon系列——趣直播课程抓取实战

作者头像
数据小磨坊
发布2018-04-11 17:45:39
8050
发布2018-04-11 17:45:39
举报

本文将以趣直播课程信息数据抓取为例,展示如何使用RCurl进行结合浏览器抓包操作进行简易数据抓取。

library("RCurl")
livrary("XML")
library("rlist")
library("dplyr")
library("jsonlite")

按照常规的操作步骤,数据抓取首先应该通过浏览器后台确认该目标网页所使用的框架和请求类型,确认网站是否提供了api访问接口,如果可以通过API直接访问数据包,那么抓取工作将会变得极其简单,倘若没有,则才考虑直接请求整个网页并使用xpath、css、正则或者具备路径查询功能的辅助包进行数据提取。

1、查看趣直播网页后台:

url<-"http://m.quzhiboapp.com/#!/lives"

打开该网页之后,按F12键,进入Chrome浏览器开发者后台,定位到xhr栏目,在该栏目的Name请求名称列表里寻找带有参数的项目(可以直接忽略所有.js结尾的请求文件)。

我一眼就看到了一个以listOrderByPlanTs?limit=30命名的请求项目,该项目中含有list关键词、limit关键词,这些关键词很可能是api用于限定信息展示条目的限制参数。

下一步确认这一条是否是我们需要的请求,选中这一条请求并鼠标单击,首先定位到右侧Preview栏目并点开,当你看到排的整整齐齐的josn数据包到的时候,毫无疑问这就是我们需要找的宝藏了。

接下来干什么呢,当时是查看该请求的请求类型,参数提交情况,以及请求参数、返回内容格式了。

从General栏目可以看到该请求是一个GET请求,请求地址是: http://m.quzhiboapp.com/api/lives/listOrderByPlanTs

从Request Headers中可以看到参数提交时优先接受json格式,但同时也可以接受text/plain(纯文本)。 User-Agent是一个重要的请求报头参数,告知目标服务器该请求的客户端设备类型。在该栏目里还有两个不常见的参数——X-Requested-With、X-Session,先不用管如果之后影响请求结果再添加。

从Response Headers中可以得知服务器 返回的数据类型是application/json格式,utf-8编码。这决定着我们使用什么工具来解析返回内容。

最后一个Query String Parameters 项目是GET请求需要提交的参数,本例只有一个limit参数,用于限定单次请求返回的信息条目数,GET请求允许请求参数直接构造在请求URL里面。

2、构造GET请求:

url<-"http://m.quzhiboapp.com/api/lives/listOrderByPlanTs"
header=c(
    "Accept"="application/json, text/plain, */*",
    "User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
    )
Param<-list("limit"=30)
chandle<-getCurlHandle(debugfunction=debugGatherer()$update,followlocation=TRUE,cookiefile="",verbose = TRUE)
content<-getForm(url,httpheader=header,.params=Param,.encoding="utf-8",curl=chandle)

查看状态码:

getCurlInfo(chandle)$response.code
#[1] 200

OK!!!

打印一下content的内容:

print(content)

完美,接下来解析内容,之前说过返回内容是json,那么这里就需要使用具备json处理能力的包进行处理。

mycontent <- content %>% fromJSON() %>% `[[`(2)

非常规整的数据框,都不用怎么做清洗和缺失值替补,实在是太完美了。

3、封装抓取函数:

接下来肯定会有小伙伴要问了,难倒只能抓这么点数据吗,这种情况下应该如何获取所有课程信息,怎么从网页后台进行检索,确定有多少课程量。

这个问题我也有疑问呢,带着这个疑问 ,我们再次造访Chrome后台。

遗憾呢,真的是看不到总课程量,只能显示30条,怎么办,试一试暴力方法!!!

直接把我们请求的url地址po到浏览器然后访问。

我们直接进入了这个json课程数据包,因为limit设置的30,所以信息自然就是30条喽,不信你用Ctrl+F查找一下关键字,输入一个课程id:liveId,输入框直接显示了该页面一共有多少个liveId数目,没错就是30个。

然后我有个大胆的想法,我们可以篡改url啊我擦~

改成100果然就显示100了哈哈哈,那就索性再大胆一些,改成1000如何???

你会发现改成1000的时候,页面的liveId只增加了12个,是不说一共只有112门课程呢,那我们就多试几次喽,分别改成200、300、500试一试。

可以看到limit参数自200以后始终都没有增加过,一直停留在112,目测一共就这么多了。

当显示出了112门课程的时候,你可以直接Ctrl+S保存该网页为.json文件,直接解析,当然我们还是要做的优雅一点,直接写在请求语句中,然后友好的返回规整的数据框。

url<-"http://m.quzhiboapp.com/api/lives/listOrderByPlanTs"
header=c(
"Accept"="application/json, text/plain, */*",
"User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
)
Param<-list("limit"=150)
chandle<-getCurlHandle(debugfunction=debugGatherer()$update,followlocation=TRUE,cookiefile="",verbose = TRUE)
content<-getForm(url,httpheader=header,.params=Param,.encoding="utf-8",curl=chandle)
getCurlInfo(chandle)$response.code
[1] 200
mycontent <- content %>% fromJSON() %>% `[[`(2);nrow(mycontent)
[1] 112

啦啦啦,多么完美的结局呀,你看数据框都不用处理缺失值,简直是太神奇了。接下来我们仅需要剔除那些我们不想要的列就可以了。

head(mycontent)
names(mycontent)
 [1] "liveId"          "subject"         "attendanceCount" "needPay"         "coverUrl"        "previewUrl"     
 [7] "amount"          "maxPeople"       "conversationId"  "status"          "planTs"          "beginTs"
[13] "endTs"           "ownerId"         "shareIcon"       "created"         "updated"         "attendanceId"   
[19] "shareId"         "owner"           "topic"           "canJoin"         "realAmount" 
invalid<-c("previewUrl","shareIcon","attendanceCount","shareId","canJoin")
myresult<-setdiff(names(mycontent),invalid) %>% mycontent[.]
head(myresult);dim(myresult);str(myresult)

OK,思路整理完了,现在开始应该封装一个像模像样点儿的自动化小爬虫程序了!

myforce<-function(url){
    header=c(        
    "Accept"="application/json, text/plain, */*",
    "User-Agent"="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
        )
    Param<-list("limit"=150)
    chandle<-getCurlHandle(debugfunction=debugGatherer()$update,followlocation=TRUE,cookiefile="",verbose = TRUE)
    mycontent<-getForm(url,httpheader=header,.params=Param,.encoding="utf-8",curl=chandle)  %>% fromJSON() %>% `[[`(2) 
    print(getCurlInfo(chandle)$response.code)
    invalid<-c("previewUrl","shareIcon","attendanceCount","shareId","canJoin")
    myresult<-invalid %>% setdiff(names(mycontent),.) %>% mycontent[.]
    print("everything is OK")
}
mydata<-myforce("http://m.quzhiboapp.com/api/lives/listOrderByPlanTs")
[1] 200
[1] "everything is OK"

看到了令人赏心悦目的200,和everything is OK,今天午饭都有食欲啦~~~

来劲了顺便给你个Python版吧~

import json
import pandas as pd
from urllib.parse import urlencode 
from urllib.request import urlopen,Request
def getdata(url):
    #postdata
    values = {'limit':150}
    link=url+'?'+ urlencode(values)
    #headers
    header = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
    'Accept':'application/json, text/plain, */*'
    }
    response = urlopen(Request(link,headers=header))
    #查看请求状态码
    print(response.getcode())
    #使用json方法解析返回的josn数据包
    myresult=json.loads(response.read())
    print(len(myresult["result"]))
    mydata=pd.DataFrame(myresult['result'])
    invalid=["previewUrl","shareIcon","attendanceCount","shareId","canJoin"]
    full=list(set(list(mydata.columns)).difference(set(invalid)))
    print("everything is OK")
    return(mydata[full])
#提供URL,运行抓取程序获取数据:
url="http://m.quzhiboapp.com/api/lives/listOrderByPlanTs"
mydata=getdata(url)
200
112
everything is OK
mydata.head(10)
mydata.info()

由于mydata里面的owner和topic字段仍然是嵌套字典,没有铺平,接下来我们使用列表表达式铺平嵌套字典。

mydata['avatarUrl']=[avatarUrl['avatarUrl'] for avatarUrl in mydata.owner]
mydata['userId']=[avatarUrl['userId'] for avatarUrl in mydata.owner]
mydata['username']=[avatarUrl['username'] for avatarUrl in mydata.owner]
mydata['name']=[avatarUrl['name'] for avatarUrl in mydata.topic]
mydata['topicId']=[avatarUrl['topicId'] for avatarUrl in mydata.topic]

删除那两列嵌套字典:

del mydata["owner"]
del mydata["topic"]
mydata.shape
(112, 21)
mydata.head()

最后就可以分析或者入库啦!!!

往期案例数据请移步本人GitHub: https://github.com/ljtyduyu/DataWarehouse/tree/master/File

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-10-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据小魔方 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云直播
云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档