掘金15W沸点简单分析(一)

吴押狱
• 阅读 1924
数据分析之数据采集(仅Web爬虫相关)。本文继续从爬虫入手。不过这次使用的是Python

一、另一种方式的爬虫

爬虫通常是:①得到目标网页URL;②发起HTTP请求得到网页数据;③使用各种方式解析网页得到想要的数据;

通常,在第②步,是不会去执行页面中的JS代码的。有些网站,会使用Ajax异步加载一些数据,然后再渲染到页面上的;或者使用JS对页面Dom做一些修改。这样都会导致第②步请求的页面中缺少、甚至是没有目标数据。这就需在获取到网页数据后,执行页面中的JS代码了。

最早是使用phantomjs+selenium。后面Chrome出了headless模式,基本就一直使用Chrome了。处理逻辑大概:①请求获取网页,执行JS代码;②再将处理过的页面数据进行保存;③后续的处理(解析网页获取数据)。

1.1 Selenium使用示例

我们就以掘金征文为例,获取该文章下所有的评论。

注: 虽然可以直接通过接口获取,但我们假设无法直接获取数据,必须执行完JS才能得到目标数据。

使用Selenium + Chrome,首先需要下载与Chrome版本对应的ChromeDriver

示例代码如下:

self.driver.get(self.article_url)
# 等待评论列表出现
WebDriverWait(self.driver, 10).until(
    EC.presence_of_element_located((By.CLASS_NAME, 'comment-list'))
)
self.save_page()

通过Selenium来操控Chrome加载网页时,通常会遇到这种问题:网络延迟,导致目标数据没有及时下载下来,但此时已将网页保存完毕。最简单的方式是,每次发生加载网页时,调用下time.sleep(5)类似的方式,但这种方式虽然简单但却比较粗暴。更好的办法是使用Selenium提供的WebDriverWait来处理。

官方文档,一定不要错过:selenium-python

1.2 页面的后续处理

将渲染后的网页保存之后,接下来就要解析提取数据了。这次我们使用XPath来解析数据。

还是先分析下网页

掘金15W沸点简单分析(一)

数据所处位置为://div[@class="comment-list-box"]/div[contains(@class, "comment-list")]/div[@class="item"]

为了处理方便,咱们仅获取第一级的评论用户和内容。

示例代码如下:

root = etree.HTML(page_source)
comments = root.xpath('//div[@class="comment-list-box"]/div[contains(@class, "comment-list")]/div[@class="item"]')
for comment in comments:
    username = self.fix_content(comment.xpath('.//div[@class="meta-box"]//span[@class="name"]/text()'))
    content = self.fix_content(comment.xpath('.//div[@class="content"]//text()'))
    print(f'{username} --> {content}')

结果数据:

掘金15W沸点简单分析(一)

二、掘金沸点的获取

咱们直接看沸点的API接口。

掘金15W沸点简单分析(一)

接口分析:

沸点接口地址:https://apinew.juejin.im/reco...
请求方式:POST
请求参数类型及格式:JSON格式数据,

{
    cursor: "0",  // 游标。 首次请求时为"0",请求响应中会含有该字段。后续请求直接使用即可
    id_type: 4,  // 沸点类别??(无关紧要)
    limit: 20,  // 分页大小 
    sort_type: 200  // 某种排序类型??(无关紧要)
}

然后我们就可以使用Python来模拟请求,获取沸点数据了。

我们使用requests来模拟请求,具体使用请看官方文档。

代码示例:

HOT_URL = 'https://apinew.juejin.im/recommend_api/v1/short_msg/hot'
json_form = {
    'cursor': '0',
    'id_type': 4,
    'limit': 20,
    'sort_type': 200,
}
resp = requests.post(HOT_URL, json=json_form)
print(resp.json())

# 数据可以正常返回
# {'err_no': 0, 'err_msg': 'success', 'data': [{'msg_id': '6864704084000112654', 'msg_Info': {'id': 980761, 'msg_id': '6864704084000112654', 'user_id': '2207475080373639', 'topic_id': '6824710203301167112', 'content': '别去找女朋友了,你的女朋友来了',

2.1 将所有数据保存下来

根据上面的示例,我们优化下代码:

def save_pins(idx=0, cursor='0'):
    json_data = {
        'id_type': 4,
        'sort_type': 200,
        'cursor': cursor,
        'limit': 200  # 该数值无限制,但过大服务器报错,或者出现用户信息缺失等情况
    }
    resp = sess.post(url, json=json_data)
    if resp.ok:
        resp_json = resp.json()
        with open(f'json_data/pins-{idx:04}.json', 'w+') as json_file:
            json_file.write(resp.content.decode('UTF-8'))
        # 是否还有更多
        if resp_json['err_no'] == 0 and resp_json['err_msg'] == 'success':
            logging.debug(f'no error, idx={idx}')
            if resp_json['has_more']:
                logging.debug(f'has more, next idx={idx+1}')
                time.sleep(5)
                save_pins(idx+1, cursor=resp_json['cursor'])
        else:
            # 出了异常
            logging.warning(resp_json['err_msg'])
            logging.debug(f'sleep 10s, retry idx={idx}')
            time.sleep(10)
            save_pins(idx, cursor)

部分数据如下:

掘金15W沸点简单分析(一)

源码已上传至GitHub, Gitee

三、后记

至此,整个热点数据获取已经结束。由于是直接请求接口返回的数据,除了部分数据重复外,几乎不用做任何数据处理。

3.1 后续处理

计划将数据简单处理、存储至MySQL数据库,然后使用superset制作图表。

3.2 针对掘金热点的建议

  • 对分页limit做限制,最大值限制为:20?
  • 针对未登录的情况,对可见数据量进行限制。
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Wesley13 Wesley13
4年前
java爬虫进阶 —— ip池使用,iframe嵌套,异步访问破解
写之前稍微说一下我对爬与反爬关系的理解一、什么是爬虫   爬虫英文是splider,也就是蜘蛛的意思,web网络爬虫系统的功能是下载网页数据,进行所需数据的采集。主体也就是根据开始的超链接,下载解析目标页面,这时有两件事,一是把相关超链接继续往容器内添加,二是解析页面目标数据,不断循环,直到没有url解析为止。举个栗子:我现在要爬取苏宁手机价
Irene181 Irene181
4年前
详解4种类型的爬虫技术
导读:网络爬虫是一种很好的自动采集数据的通用手段。本文将会对爬虫的类型进行介绍。作者:赵国生王健来源:大数据DT(ID:hzdashuju)聚焦网络爬虫是“面向特定主题需求”的一种爬虫程序,而通用网络爬虫则是捜索引擎抓取系统(Baidu、Google、Yahoo等)的重要组成部分,主要目的是将互联网上的网页下载到本地,形成一个互联网内
把帆帆喂饱 把帆帆喂饱
4年前
爬虫
爬虫什么是爬虫使用编程语言所编写的一个用于爬取web或app数据的应用程序怎么爬取数据1.找到要爬取的目标网站、发起请求2.分析URL是如何变化的和提取有用的URL3.提取有用的数据爬虫数据能随便爬取吗?遵守robots.txt协议爬虫的分类通用网络爬虫百度,Google等搜索引擎,从一些初识的URL扩展到整个网站,主要为门户站点搜索引擎和大型网站服务采
Wesley13 Wesley13
4年前
Java爬虫之JSoup使用教程
title:Java爬虫之JSoup使用教程date:201812248:00:000800update:201812248:00:000800author:mecover:https://imgblog.csdnimg.cn/20181224144920712(https://www.oschin
Stella981 Stella981
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Stella981 Stella981
4年前
Python_爬虫笔记_2018.3.19
Python\_爬虫\_笔记1.前言1.1爬虫用途:网站采集、接口采集(地图(jis热力学屋里端口/协议)、微信、知乎、)1.2基本流程:网页下载(requests)网页解析爬虫调度网页解析:在当前网站找信息、下一个入口等信息调度:调度器/
Easter79 Easter79
4年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
小白学大数据 小白学大数据
1个月前
拉勾网 Ajax 动态加载数据的 Python 爬虫解析
在招聘数据采集、职场趋势分析等场景中,拉勾网是重要的数据来源,但拉勾网采用Ajax动态加载技术渲染页面,传统的静态网页爬虫无法直接获取数据。本文将从Ajax动态加载原理入手,详解基于Python的拉勾网数据爬虫实现过程,包括请求分析、参数构造、反爬应对及数