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

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

抓取异步数据
    • 主要内容:
    • 关于异步传输AJAX
      • 什么是AJAX?
      • AJAX基本原理
    • AJAX服务端请求数据案例
    • 实战案例:抓取某东图书评价

主要内容:
  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('
  • ' + data[i].name + '
  • '
    ) } }); } </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
    

    欢迎分享,转载请注明来源:内存溢出

    原文地址: http://outofmemory.cn/langs/578318.html

    (0)
    打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
    上一篇 2022-04-11
    下一篇 2022-04-11

    发表评论

    登录后才能评论

    评论列表(0条)

    保存