Pyhon爬虫抓取Json解析错误

前言

最近在我的Python爬虫中总是会遇到json.loads()方法报错,把抓取到的原文摘出来一看,里面带有转义的 " 和 ',也就是 \"和\'。

一开始遇到这个问题就疯狂上网搜索,结果找不到能解决我问题的答案,所以就想着按照Json解析的算法做一个自己的Json解析算法。不过,这似乎十分麻烦,懒惰的我于是就做了个替换算法。针对 " 做定位,并且将 Json内的 " 替换成 \", 这样后面进行Json解析的时候就不会报错了.

4月12日更新:

遇到了一个比较特殊的Json,里面有换行符和制表符('\n'和'\t'),在python中用自带的json.loads()总是会报错,我自己写的方法也不好搞。不过因为业务特殊,这个Json不一定要在爬虫的时候就解析,而且在Java中用FastJson解析完全没有问题.(阿里爸爸牛逼),所以就干脆在python程序结束的时候调用一下Java程序就好啦.

什么,怎么调用?怎么运行jar包就怎么调呗,毕竟懒得引入python调用Java的框架了.TNT

import os
os.system("java -jar test.jar")
# 如果遇到java程序乱码,就再加上运行时的编码设置就好啦
# os.system("java -Dfile.encoding=utf-8 -jar test.jar")

代码

封装json.loads方法,进行try及在except中加入对应的处理逻辑:

def json_loads(string):
    """
    尝试将string转为json对象,如果转为json对象失败,则抛出异常,并且将错误的JSON记录在json.log中
    :param string:
    :return:
    """

    try:
        temp_json = json.loads(string)
    except json.JSONDecodeError:
        temp_json = None

    if temp_json is None:
        try:
            # REPLACE_POINT是我自己定义的常量,用于标识\', 可以参照URLDecoder,我设置的是%10AA
            string = str(string).replace("\\'", REPLACE_POINT)
            temp_json = json.loads(string)
        except json.JSONDecodeError:
            # 锚点Json中经常会出现\t
            string = string.replace("\t", "")
            try:
                temp_json = json.loads(string)
            except json.JSONDecodeError:
                # 万般无奈的情况下再用这个方法,该替换算法存在风险
                string = solve_wrong(string)
                try:
                    temp_json = json.loads(string)
                except json.JSONDecodeError as json_exception:
                    print(string)
    return temp_json
def solve_wrong(string, right=0):
    """
    在解析Json失败时, 调用此方法将错误的字符串用转义,也就是将 '"' 替换成 '\"'
    :param string: 解析错误的Json字符串
    :param right: 字符串解析的初始偏移位置,网页上的Json数据长度基本都会大过10的吧...
    :return: 转义之后的字符串
    """

    if len(string) < 10:
        # 长度比10还小的Json?逗我呢
        print("Get out,this is bullshit.")

    result = None
    while right < len(string):
        c = string[right]
        if c == '"':
            # 记录当前双引号位置
            left = right
            flag = False
            # 从当前位置向后查询
            right = left + 1
            while (right + 2) < len(string):
                if string[right] == '"':
                    # 找到与之配对的",判断是否是Json的正确结尾
                    nextc = string[right + 1]
                    if nextc == ']' or nextc == ',' or nextc == ':' or nextc == '[' or nextc == '}':

                        if nextc == ',':
                            # 可能是下一個Json對象、数组或数据的开始
                            next_nextc = string[right + 2]
                            if next_nextc != '{' and next_nextc != '"' and next_nextc != '[':
                                # 如果不是数据的开始部分,说明"就在本次字符串中
                                flag = True
                                right += 1
                                continue

                        # 说明是正确的结尾
                        if flag:
                            # 截取引号对中间的部分
                            temp = string[left + 1: right]
                            if result is None:
                                # 用result来存储string替换后的结果,如果直接更改string的话
                                # 会导致一连串的变化
                                result = string.replace(temp, temp.replace('"', '\\"'))
                            else:
                                result = result.replace(temp, temp.replace('"', '\\"'))
                        break
                    else:
                        # 找到导致Json解析错误的字符串了,现在只要移动到结尾再截取字符串就可以了
                        flag = True
                right += 1
        right += 1
    return result

算法思想

主要是依赖双指针,确定出来每一个 双引号(")对,当右指针发现"时候,判断它是不是正确的结尾,如果不是,就把flag设置为True,等到右指针指到真正的结尾时,截取引号对中间的部分,进行替换。

我就是靠硬生生盯着目标Json的形式,总结出来的结尾,顺便说一句,我用开发者模式看到的Json是有转义符号的,不过等我用程序抓来之后,python似乎就给当作转义字符识别了,很难受。。。

你可能感兴趣的:(Python,python)