Python公开课 - 数据抓取之Ajax

前言

目前HTML页面分为静态网页和动态网页,动态页面是指前端页面的主要代码一样,但是动态展现部分是根据后台的数据不同而表现各异。

对于静态页面的抓取比较简单,但是往往动态页面的价值更大,因为它联系着后端的结构化数据。

其中Ajax技术的出现又让前端动态页面的展现更加灵活,用户体验更好,同时给爬虫的抓取也带来的更大的技术难度。

什么是Ajax

Ajax,全称为Asynchronous JavaScript and XML,即异步的JavaScript和XML。 它不是一门编程语言,而是利用JavaScript在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。

简单来说就是数据加载是一种异步加载方式,原始的页面初始加载的时候并不含有该数据,而是待页面加载完后或用户触发后,前端再向服务器请求某个接口获取数据,然后数据才被处理从而渲染到网页上,这整个过程,就是发送了一个Ajax请求。

实战新浪微博 - 抓取每日热门

第一步:分析抓取源页面

我们首先要做的就是比较H5页面与PC页面,评估抓取难度。

目前网站建设一般来说会有普通HTML页面,适合用户在PC下的浏览器宽屏模式进行访问,另外也会建设一个H5页面,让用户在手机的小屏浏览器上也有不错的体验。

但是这个对于我们来说都不重要,因为它们两周的后台数据源都是一样的,我们需要的是比较哪种页面对于我们来说更容易抓取。

新浪微的首页https://weibo.com/?category=0,可以直接访问不用登陆

新浪热门微博

新浪的热门微博在H5下的地址是https://m.weibo.cn/,也可以直接访问不用登陆

新浪微博热门

但是比较之后,我们发H5页面的结构更简单些,这样对于后期的页面抽取也是有帮助的,因此我们选择以H5页面作为抓取源

第二步:分析Ajax请求

传统页面的翻页是通过下一页按钮来实现,新浪微博也是类似,不过是使用的Ajax技术来实现。

新浪微博翻页

通过Chrome浏览器来抓包分析,我们每次将页面拖到底部,并不断滑动页面,可以看到页面底部有一条条新的微博被刷出,而开发者工具下方也一个个地出现Ajax请求, 如图所示:

新浪微博翻页请求

第三步:分析响应内容

点击并展开该请求,看看新浪的后台都响应了啥内容呢,该响应返回了Json数据,其中核心数据放在了data字段中,内嵌的微博内容是List结构构成。详细内容如下:

新浪微博Ajax响应

第四步:提取内容

由于是Json数据,所以提取内容非常方便,我们只用选择我们需要的字段数据,并进行裁剪即可。

例如我们需要转发数,评论数,id,内容等信息,直接可以通过json的key, value值来获取

代码如下:

def parse_page(json):
    items = json.get('data').get('cards')
    for item in items:
        item = item.get('mblog')
        if item == None:
            continue
        weibo = {}
        weibo['id'] = item.get('id')
        weibo['text'] = pq(item.get('text')).text()
        weibo['attitudes'] = item.get('attitudes_count')
        weibo['comments'] = item.get('comments_count')
        weibo['reposts'] = item.get('reposts_count')
        yield weibo

提取后内容如下:

{'reposts': 39467, 'attitudes': 45754, 'comments': 24316, 'id': '4330663866478723', 'text': '刚才且且在讨论吴秀波小三的私人生活,就去看了看陈昱霖的Ins,当场就昏迷了,基本上是比佛利娇妻网红版。\n\n之前陈昱霖在爆料时,说得凄凄惨惨戚戚,被吴秀波圈养在横店的房间里,给他洗衣搓背炖汤侍寝。几年不羁情,一把辛酸泪。\n\n结果看Ins感觉一年365天都在全世界旅游,入住的全是安曼四季范思哲酒 ...全文'}
{'reposts': 29327, 'attitudes': 62777, 'comments': 11528, 'id': '4330532781865649', 'text': '【这是地球的#十年对比挑战#】地球的变化,可能比我们想象中更快!敬畏生命,关爱自然,一起守护我们共同的家。支持请转! NowThis的秒拍视频'}
{'reposts': 14562, 'attitudes': 50973, 'comments': 5229, 'id': '4330596832125262', 'text': '【回忆杀!#手机十年对比挑战#:2009年,人们都用什么手机?】2009年到2019年这十年间,科技发展迅速,诺基亚手机从行业巨头跌入谷底,三星,小米,华为手机崛起,电脑升级换代迅速,各种新的科技产品不断出世。2029年,会有什么样的高科技呢?@全球视频大魔王 全球视频大魔王的秒拍视频'}
{'reposts': 12206, 'attitudes': 37263, 'comments': 9191, 'id': '4330686271455274', 'text': '【逆转获胜!国足2-1胜泰国闯进八强!】#2019年亚洲杯#1/8决赛,中国队迎战泰国!上半场国足全面处于被动,第31分钟被对手利用角球机会打进一球,0-1落后!下半场国足展开绝地反击,里皮第63分钟的换人成为比赛转折点,第67分钟,刚刚替补出场的肖智头顶脚踢连续两脚射门将球打进,1-1!3分钟之后,郜 ...全文'}
{'reposts': 29706, 'attitudes': 59720, 'comments': 12003, 'id': '4330598409696735', 'text': '来来来,新鲜出炉,《飞驰人生》剧情版预告片电影飞驰人生的微博视频'}
{'reposts': 64645, 'attitudes': 207631, 'comments': 23075, 'id': '4330615652923843', 'text': '明兰解除刘海封印,开启新副本'}
{'reposts': 5472, 'attitudes': 26382, 'comments': 58447, 'id': '4330589911599564', 'text': '#娱乐圈好男人#这两天,吴秀波国民大叔的形象彻底崩塌,有人提问:娱乐圈还有哪些好男人?网友纷纷提名:潘粤明、邓超、周杰伦、陈信宏、靳东。你心中的娱乐圈好男人是谁?'}
{'reposts': 241449, 'attitudes': 179559, 'comments': 59618, 'id': '4330665946062381', 'text': '今晚 爽\n演唱会见'}
{'reposts': 79853, 'attitudes': 108235, 'comments': 13535, 'id': '4330546173624314', 'text': '1、节目里大概只是关于我1/3的呈现,宅和养生是我认为的舒适并且享受的生活方式,但是并不代表我只宅在家里养生,我们的生活需要给自己留独立的空间去放松调整,当然也需要在独立的空间之外,去积极阳光的生活。\n2、我的确是一个容易动感情的人,跟朋友一起更是容易情绪激动。一激动就会哭...但是哭其 ...全文'}

小结

本章介绍了什么是Ajax,并且以新浪微博为例介绍了如果来抓取Ajax的数据内容,实际情况会更复杂,会在后面的章节中进行介绍。

完整代码

import requests
from urllib.parse import urlencode
from pyquery import PyQuery as pq

def get_page(page):
    params = {
      'containerid':'102803', 'page': page}
    url = 'https://m.weibo.cn/api/container/getIndex?openApp=0' + urlencode(params)
    r = requests.get(url)
    return r.json()

def parse_page(json):
    items = json.get('data').get('cards')
    for item in items:
        item = item.get('mblog')
        if item == None:
            continue
        weibo = {}
        weibo['id'] = item.get('id')
        weibo['text'] = pq(item.get('text')).text()
        weibo['attitudes'] = item.get('attitudes_count')
        weibo['comments'] = item.get('comments_count')
        weibo['reposts'] = item.get('reposts_count')
        yield weibo

for i in range(1, 10):
    json = get_page(i)
    results = parse_page(json)
    for result in results:
        print(result)


相关阅读


相关推荐
  1. Python实战 - 爬虫代理IP池的实现
  2. 脱单!武汉的相亲角在哪你知道吗?
  3. 沈阳市和平区育婴童幼儿园 - 沈阳幼儿园黄页
  4. 承德市第七中学
  5. 辽宁省鞍山市台安县百利华府幼稚园 - 鞍山幼儿园黄页
  6. 蓝天幼儿园(西新华街) - 哈尔滨幼儿园黄页
  7. 宁波市鄞州区钟公庙中心小学
  8. 古韵南京 - 二日游
  9. 武汉一女子七天被骗220万
  10. 湖北将发放消费券 - 武汉新鲜事
  11. 广州市荔湾区芳华实验幼儿园 - 广州幼儿园黄页
  12. 三个傻瓜
  13. 内蒙古自治区呼和浩特市新城区博爱双语幼儿园 - 呼和浩特幼儿园黄页
  14. 保定市人民警察学校
  15. 北京市大兴区观音寺小学
  16. 披着被单的国王
  17. 面试之物联网卡与互联网卡的区别
  18. 青龙满族自治县第一中学(青龙一中)
  19. 阿贝许愿
  20. 呼和浩特市新城区金龟子艺术幼儿园 - 呼和浩特幼儿园黄页
  21. 南海区罗村高级中学
  22. 石家庄第二十一中学
  23. 巨鹿大战
  24. 耿家庄小学
  25. 泰宁县开善中学
  26. 黄骅市常郭镇滕家堡村小学
  27. 大狼托克打电话
  28. 沈阳市铁西区光明二小
  29. 生活不易,酒在远方
  30. 央媒聚焦!国庆假期173.78万人次打卡大美黄陂
  31. 南辛镇王庄小学
  32. 广州市白云区金贝贝艺术幼儿园 - 广州幼儿园黄页
  33. 南京市小西湖小学
  34. 株洲市新明小学
  35. 涞水县祖冲之中学
  36. 飞上屋顶的公鸡
  37. 幼儿园入学准备物品清单
  38. 武汉推出越王勾践剑交通卡
  39. 重庆双福育才
  40. Python公开课 - Requests高级功能
  41. 吉林大学第一附属小学(吉大一小)
  42. 沈阳市沈北新区华美中英文幼儿园 - 沈阳幼儿园黄页
  43. 武汉动物园火烈鸟孔雀排队打疫苗
  44. 小木屋
  45. 哈尔滨市第六十八中学校
  46. 易中天给英雄武汉的一首诗 - 武汉新鲜事
  47. 1岁婴儿头围48正常吗 - 育儿经验
  48. 蜜蜂与蝴蝶
  49. 吉林省吉林市建设双语幼儿园 - 吉林市幼儿园黄页
  50. 车队管理及解决方案 - 附SkyBitz & Omnitracs成立车队管理合作伙伴
  51. Python公开课 - 数据抓取之Selenium使用(下)
  52. 牛衣对泣
  53. 武汉00后大二学妹拍视频月入七十万
  54. 郑中国际学校(郑中实验学校)
  55. 小人国奇遇
  56. Python公开课 - 异常处理
  57. Vim - 基础教程
  58. 武汉女子网上做兼职被骗六十五万
  59. Python公开课 - 页面解析之pyquery
  60. 佛山市罗村街道中心小学
  61. 事发武汉农夫山泉矿泉水内惊现大量虫卵