如何使用API爬取数据,它和网页爬虫有什么区别?

背景

很多互联网公司往往都有着存储自己用户信息的数据库,数据库里的数据也基本被工程部门解析得很干净了(爬虫技术的使用或底层数据解析主要是开发部门或者数据采集工程部的工作),所以许多业务类的数据分析师们仅使用HSQL等工具就能较轻松地获得所需的海量数据。

但市面上还有一些中小型B2B公司,他们并不像B2C类的企业,依赖自身的用户信息做产品迭代或业务增长。他们主要依靠工程部门解析第三方数据,将结果输送到产品开发部门进行业务平台的搭建和可视化。而获取第三方数据的过程需要使用到第三方API接口,这也是为什么这些企业要求应聘数分岗位的候选人要有调用API的经验,因为就算公司有自己的数据库,但这毕竟都是工程部门选择性爬取和整理后的结果,你可能会面临数据库并没有你想要的数据的困境,这个时候就需要你用类似的方法,自己采集数据。
在这里插入图片描述

API简介

调用API这个过程也是爬虫中的一种。在爬虫中,提及API的地方通常有两处,一个是库API,另一个是数据API。

库API

库API通常指开发人员开发了一个库(例如python库),并提供了一个接口供使用者调用这个库。这就好比,我们想去包裹储物柜取我们的快递,必须要输入正确的信息才能拿到我们的快递,这个信息就是一个API接口,帮助我们准确定位到这个库并调用它。

数据API

在产品开发或者网页开发中,数据API就像后端递给前端的数据线。后端人员已经整理好想要展示的数据,只需要通过这根数据线传输给前端的开发人员,前端就可将其按需求进行后续的可视化。而且这个接口还可供外界使用。

与网页爬虫不同的是,数据API的设计更为简单高效,这个接口已经存储好大家所需要的数据,我们不需要再花过多的精力去解析网页。并且网页数据爬取往往会对服务器造成压力,如果你的代码没有设置好合理的类人的网页浏览频率,会有IP被封的风险。

但数据API也有一些缺点。虽然市场上有很多API产品都可供外界使用,但许多免费的接口对爬取量有很大的限制,如果你的爬取需求很大,是需要付费的。

简单的API爬虫实例

下面我会以使用 Facebook Graph API 爬取数据为例,大致记录一下常见的数据API调用流程。

  1. 调用接口信息:提供API的调用地址(通常为URL格式),这个地址就类似于帮助我们定位想取的包裹在储物柜的哪一行哪一列。
  2. 请求获取数据:利用HTTP协议请求传递数据,通常会调用到python中request包里的get函数。
  3. 设置请求参数:需要提供请求参数,也就是你需要告诉API接口你想获得什么样的信息,例如在本例中我需要的有created_time(博文发布时间),post_id(博文_id)等信息。

Facebook Graph API 介绍文档

虽然一个get函数就可以帮助我们实现HTTP协议请求,但很多时候请求这个URL是需要身份认证的。例如以下的代码就会报错:

import requests
r = requests.get('https://facebook.com/user_id')
r.json()

并返回:需要身份权限。所以在使用任何一个API接口时最好事先阅读网站的使用文档,看看请求协议所需要的具体信息有哪些。

{'documentation_url': ''https://facebook.com/user_id/#get-the-access-token',
 'message': 'Requires authentication'}

在脸书API的官方使用手册中也可以看到,如果我想获得某个脸书账号的po文信息,我需要实现获得这个账号的token。如果你想获得除自己外的其他账号信息,你也同样需要事先拿到他们的token。这里会有相应的获取token的介绍 ->如何获得脸书账号的access token

获取了token之后,测试以上代码便可获得以下结果:
在这里插入图片描述

代码示例

目的:获取某个账户从2020.03.01至2020.03.07每条视频博文的观看次数,各个国家,各个性别以及各年龄段的观看时长,分析该博主在这周内视频内容的表现。

1. 首先我需要拿到3.1至3.7之间每条博文的ID(post_id)
2. 筛选出仅为视频的博文ID
3. 需要获取每条视频博文的观看次数,各个国家的观看时长
4. 将json格式的数据整理成dataframe格式 
5. 将观看时长可视化

1. 导入所需的包

import pandas as pd
import json, datetime, requests
from datetime import date, timedelta, datetime
import numpy as np
from pandas.core.frame import DataFrame

2.创建爬取数据的函数

def get_list_of_fb_post_ids(fb_page_id, fb_token, START, END):
    
    ''' 
    Function to get all the post_ids from a given facebook page during certain time range
    '''
    
    posts=[]  #用来存储所有博文的post_id
    graph_output = requests.get('https://graph.facebook.com/'+fb_page_id+'?fields=posts.limit(10){created_time}',params=fb_token).json()
    posts+=graph_output['posts']['data'] 

    graph_output = requests.get(graph_output['posts']['paging']['next']).json()
    posts+=graph_output['data'] 

    while True: #一直读取next_page,直到某次读取的记录的时间小于你设置的开始时间
        try:
            graph_output = requests.get(graph_output['paging']['next']).json()
            posts+=graph_output['data']
            if graph_output['data'][-1]['created_time']<=START:
                break
        except KeyError:
            break
            
    df_posts=pd.DataFrame(posts)
    df_posts=df_posts[(df_posts.created_time>=START)&(df_posts.created_time<=(datetime.strptime(END, "%Y-%m-%d")+timedelta(days=1)).isoformat())]
    df_posts.columns = ["timestamp", "post_id"]
    return df_posts 

3.给变量赋值,抓取post_id

fb='EAAIkwQUa1WoBAFWmq90xbMfLHecpRga****************'
fb_token = {'access_token': fb}
user_id='1404******'
output=get_list_of_fb_post_ids(user_id,fb_token,'2020-03-01','2020-03-07')

获得结果如下:
在这里插入图片描述

4.获取每条视频博文的相关数据

## 设定好想要获取的每条视频博文的信息
Fields = '?metric='+'post_video_views,post_video_view_time_by_region_id'
list_metrics=[ 'post_video_views','post_video_view_time_by_region_id']
def get_video_insights(output,fb_token):
   final_output=pd.DataFrame()
   for i in output.index.values:
       post_id = output['post_id'][i]
       Type = requests.get('https://graph.facebook.com/'+post_id+'?fields=type',params=fb_token).json()
       if Type['type'] == 'video': #筛选出仅为视频的博文记录
           try:
               insights_output = requests.get('https://graph.facebook.com/'+post_id+'/insights{}&period=lifetime'.format(Fields),params=fb_token).json()
               list1=list_metrics
               metrics=[]
               for j in range(0,len(list_metrics)):
                   metrics.append(insights_output['data'][j]['values'][0]['value'])
               #print("metrics get")
               metrics=DataFrame(metrics).T
               metrics.columns=list1
               col_name = metrics.columns.tolist()
               col_name.insert(col_name.index('post_video_view_time_by_region_id'),'timestamp')
               col_name.insert(col_name.index('timestamp'),'post_id')
               metrics=metrics.reindex(columns=col_name).reset_index()
               metrics['post_id']=output['post_id'][i]
               metrics['timestamp']=output['timestamp'][i]
               final_output=final_output.append(metrics)
           except:
               pass
   return final_output

结果输出为:
在这里插入图片描述

5.将json格式的数据整理成dataframe格式
从以上的结果中我们可以看出,在这一周内,该博主共发布了6条视频博文,其中播放量最多的为3.3号其中的一条,多达四十多万次。但各地区观看时长这个指标的格式为json格式,我们需要对其进行单独处理。

先查看region这一列的数据结构:
在这里插入图片描述

从上面的结果可以看出,我们需要遍历该列的每一行,生成一个新的da’ta’frame, 将每个国家作为一个列,并将其所对应的的数值一一存储进去。

#遍历 post_video_view_time_by_region_id 这一列的每一行
Region=pd.DataFrame()
metrics.index=range(len(metrics)) #重新定义index
metrics['post_video_view_time_by_region_id']=metrics['post_video_view_time_by_region_id'].astype('str')
for j in metrics.index.values:
    e=eval(metrics['post_video_view_time_by_region_id'][j]) #返回字符串内的值,直接返回一个dict
    single_graph = []
    for i in e.keys():
        single_graph.append(e[i])
    single=pd.DataFrame(single_graph).T
    single.columns=list(e.keys())
    Region=Region.append(single)

显示结果如下:
在这里插入图片描述

6. 将观看时长可视化
首先我们需要处理一下Region这个表的数据,我们需要将每一个列名拆分为国家和城市。这样做事为了更加便捷地将以上的数据映射到美国地图上,从视觉上来直观判断哪一个州的用户更加喜欢该博主的视频内容。

o=Region.mean().to_dict() #算出每个城市的平均观看时长
dataset=pd.DataFrame(pd.Series(o),columns=['view time'])
dataset=dataset.reset_index().rename(columns={'index':'region'})
dataset['state']=dataset['region'].map(lambda x: x.split('-')[0]) #将列名分为国家和地区
dataset['country']=dataset['region'].map(lambda x: x.split('-')[1])#将列名分为国家和地区

处理后的结果为:
在这里插入图片描述

最后我们只需要筛选出美国的地区,将数据转化到一张美国地图上,便大功告成了。
在这里插入图片描述

在这里插入图片描述

从地图中我们可以分析出,该博主的视频深受德克萨斯州与加州人民的喜爱,除了不断尝试能迎合这两个州的用户的视频策略之外,还需要进一步调研为何其他州的视频播放时长远远不及它们。综合以上的信息,博主在后期的视频制作中可以使其更有有地域特征,并推荐博主使用脸书的地域分发功能,将不同特色的视频内容分发至不同的地区,更高效地迎合用户们的品味和爱好,优化自己的自媒体营销工作。

以上就是利用Facebook Graph API 爬取数据的步骤啦,如有不足或解释得不正确的地方,还请小伙伴们批评指正。: )

发布了2 篇原创文章 · 获赞 2 · 访问量 988

猜你喜欢

转载自blog.csdn.net/weixin_43944997/article/details/105502469
今日推荐