爬虫高级应用(13. 抓取异步数据)

主要内容:

  1. 什么是异步数据加载
  2. AJAX的基本概念
  3. 如何获取异步数据使用的URL
  4. 抓取异步数据
  5. 项目实战:分析某东商城图书评论数据,并抓取这些数据

关于异步传输AJAX

什么是AJAX?

1、异步,请求和下载异步,不占用主线程,即使加载数据缓慢,不会出现页面卡顿
2、传输数据的格式,XML->JSON

AJAX基本原理

  1. 发送请求,Web端页面中实现业务逻辑与页面交互的JavaScript语言, IE7+、FireFox,Chrome,Safari浏览器等,需使用XMLHttpRequest对象发送请求,而IE7版本以下的浏览器需要使用下面的代码串讲Microsoft.XMLHTTP对象xmlhttp = new ActiveXObject(“Microsoft.XMLHTTP”)
  2. 解析响应,响应主要是指JSON格式的数据。使用JSON.parse(result)得到JavaScript的JSON的数据
  3. 渲染页面

AJAX服务端请求数据案例

  1. 使用Flask框架模拟实现一个异步加载的页面。页面使用模板显示,通过jQuery想服务端发送请求,获取数据后将数据显示在页面上
  2. 知道了异步传输的URl,就可以通过requests等网络去通过URL进行抓取,不过返回的数据格式不是HTML,也不是XML,而是JSON。
  3. 所以不能使用XPath和CSS选择器处理,而是使用json模块中的loads函数将字符串形式的JSON转换为Python字典

服务器端

from flask import Flask,render_template
from flask import make_response
import json
app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')
@app.route('/data')
def data():
    data = [
        {'id':1,'name':'PyQt5(Python)实战视频课程'},
        {'id':2,'name':'Electron实战'},
        {'id':3, 'name': '征服C++ 11'},
        {'id':4, 'name': '征服Flask'},
    ]
    response = make_response(json.dumps(data))
    return response

if __name__ == '__main__':
    app.run(host = '0.0.0.0', port='1234')

html页面内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>异步加载页面</title>
    <script src="/static/jquery.js"></script>
</head>
<body onload="onLoad()">
<h1>视频课程</h1>

<ul id="video_list">

    <li>人工智能-机器学习实战视频课程</li>
    <li>用C++和Go开发Node.js本地模块</li>
    <li>Go Web实战视频教程</li>
    <li>Python科学计算与图形渲染库视频教程</li>
</ul>
<script>

    function onLoad()
    {
        $.get("/data", function(result){
            data = JSON.parse(result)
            for(var i = 0; i < data.length;i++) {
                $('#video_list').append('<li>' + data[i].name + '</li>')
            }
        });
    }
</script>
</body>
</html>

jquery.js文件内容
可以自行到网上下载,博主用的是jquery1.7.2版本

请求客户端

import requests
import json
from lxml import etree
result = requests.get('http://localhost:1234/data')
# 由于返回的数据包含中文(unicode编码),所以需要将其转码
print(result.text)
text = result.text.encode('utf-8').decode('unicode-escape')
print(text)
# 将字符串形式的JSON转换为Python字典
data = json.loads(text)
print('个数:',len(data))
# 输出返回的所有视频课程名称
for value in data:
    print(value['name'])

通过url的形式可以请求到数据,不过数据是以json的形式存放
在这里插入图片描述

抓取的异步数据后,进行解析,在控制台输出数据:
在这里插入图片描述

实战案例:抓取某东图书评价

  1. 首先进入某东图书的官网,选取一本图书
    https://item.jd.com/12715627.html
    在这里插入图片描述

  2. F12进入开发者模式,找到异步传输的评论内容URL
    这里将一个小技巧,打开F12审查元素后,会看到很多眼花缭乱的条目,一下子找不出哪一个是评论的异步传输url,先清除一下当前的条目,再点击页面上评论的按钮,再传输过来的就是关于评论的条目了,数量上也会少很多。
    在这里插入图片描述
    双击可以查看异步页面传输的是什么
    异步数据的URL: https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=12715627&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1

在这里插入图片描述

  1. 对其进行请求,注意要加Cookie
    注意:这里Cookie的获取,需要用自己的账号登录网页后再获取某东上自己的Cookie,如果没有登录,请求网页仍然会被拦截,所以在爬虫无法解析页面的时候,最好打印一下页面的内容,大多是因为请求头设置的不够完全导致无法请求到页面的代码。
    复习:如果忘记了如何获取自己的Cookie,请复习查看requests网络库内容: 如何获取及设置Cookie.

  2. 实操代码:
    这里的代码需要替换url,Cookie,再解析JSON的数据

import requests
import re
import json
import csv
import os
# 设置请求头(User-Agent)
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 ',
    'Accept': '*/*',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'Referer': 'https://item.jd.com/',
    'Connection': 'keep-alive',
    'Cookie': '替换成自己的Cookie',
    'Host': 'club.jd.com'
}
# 限定抓取的评论数
fetch_comment_count = 15
# 设置代理
proxies = {
    "https":"https://27.220.121.173:49508"
}
index = 0
page_index = 0
flag = True # 用于控制循环的退出
while flag:
    url = '''https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=12417265&score=0&sortType=5&page={}&pageSize=10&isShadowSku=0&fold=1'''.format(page_index)
    print(url)
    page_index += 1
    # html = reqests.get(url,headers=header,proxies=proxies
    # 抓取评论页面
    html = requests.get(url,headers)
    # 获取抓取的内容,这里需要先按照iso-8859-1格式编码
    text = str(html.content, encoding='iso-8859-1')

    # 下面的代码替换返回数据的部分内容,因为返回的数据并不是标准的JSON格式
    leftIndex = text.find('{')
    rightIndex = text.rfind('}')
    json_str = text.replace('fetchJSON_comment98(', '')
    json_str = json_str.replace(")", '')
    json_str = json_str.replace("null", '"null"')
    json_str = json_str.replace(";", '')
    print(json_str)
    json_obj = json.loads(json_str)
    # 循环输出评论数据
    for i in range(0,len(json_obj['comments'])):
        try:
            # 这里要进行iso-8859-1编码,然后在解码,否则会出现乱码
            # 按iso-8859-1编码是指按原样将字符转换为字节流
            # 获取评论内容
            comment = json_obj['comments'][i]['content'].encode(encoding='iso-8859-1').decode('GB18030')
            # 删除评论内容是用户 没有填写评论内容
            if comment != '此用户未填写评价内容':
                print('<',index + 1,'>',comment)
                # 获取评论时间
                creationTime = json_obj['comments'][i]['creationTime']
                # 获取昵称
                nickname = json_obj['comments'][i]['nikename'].encode(encoding='iso-8859-1').decode('GB18030')
                print(creationTime)
                print(nickname)      print('__________________________________________________________')
                index += 1
        except:
            pass
        if index == fetch_comment_count:
            flag = False
            break
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值