爬虫中遇到的JSON问题

守給你的承諾、 提交于 2020-01-14 11:10:56

        帮朋友爬一个政府公告文件,整个流程挺简单的,但下了两个文件之后在第三个文件卡住了。经过排查原因,发现是在调用 json 库中的方法 loads 时发生了错误。简单描述一下流程,首先,爬取一个链接可以得到一个 response,response 中的 text 属性也就是我们想要提取的内容,类型是一个字符串,同时也是一个 json 文件。何谓 python 中的 json 对象呢?我的理解是主要以花括号 {}、中括号 []、冒号: 和逗号来表示的一种格式,本质上就是键值对。例如我爬取得到的 response.text 经过 print 如下

{"Succeed":"1","Message":"成功","Data":{"pos":0,"total_count":3743,"rows":[{"id":"1","data":["江门市新会区会城梅江南路22号海棠公馆1座","<a href=\"/public/web/ysxm_JM?ysxmid=635FD571C35C412E85E67BC85A854B73&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">海棠公馆</a>","<a href=\"/public/web/Yszxx?ysxmid=635FD571C35C412E85E67BC85A854B73&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020009号</a>","<a href=\"/public/web/KfxmList?kfsid=4407050408&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市美溢房地产开发有限公司</a>","枢纽新城今洲路南侧、规划梅江南路东侧地块","新会区"]},{"id":"2","data":["新会区大泽碧桂园凤凰花园33座","<a href=\"/public/web/ysxm_JM?ysxmid=2CF13AC191BF4984B6D4C94A23CBC576&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">大泽碧桂园凤凰花园</a>","<a href=\"/public/web/Yszxx?ysxmid=2CF13AC191BF4984B6D4C94A23CBC576&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020008号</a>","<a href=\"/public/web/KfxmList?kfsid=440705-133574&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市新会区粤航投资有限公司</a>","大泽碧桂园凤凰花园","新会区"]},{"id":"3","data":["江门市新会区会城潮江路20号御锦世家花园3座","<a href=\"/public/web/ysxm_JM?ysxmid=C9BEC95A7D1C474BA86ABC33A8B1F73A&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">御锦世家花园</a>","<a href=\"/public/web/Yszxx?ysxmid=C9BEC95A7D1C474BA86ABC33A8B1F73A&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020007号</a>","<a href=\"/public/web/KfxmList?kfsid=4407050404&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市新会区诚恩置业发展有限公司</a>","江门市新会区会城城东通天埠(土名)","新会区"]},{"id":"4","data":["江门市新会区会城明德一路36号博富名苑9座","<a href=\"/public/web/ysxm_JM?ysxmid=A3048088DE9041E0839EE0FC96604F74&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">博富名苑</a>","<a href=\"/public/web/Yszxx?ysxmid=A3048088DE9041E0839EE0FC96604F74&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020006号</a>","<a href=\"/public/web/KfxmList?kfsid=4407050397&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门博富置地发展有限公司</a>","江门市新会区会城街道文华路与明德路交叉口的西北角地块","新会区"]},{"id":"5","data":["江门市新会区会城明德一路36号博富名苑1座","<a href=\"/public/web/ysxm_JM?ysxmid=44A66CCEAC50415D9C8B3BD7C45E64A5&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">博富名苑</a>","<a href=\"/public/web/Yszxx?ysxmid=44A66CCEAC50415D9C8B3BD7C45E64A5&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020005号</a>","<a href=\"/public/web/KfxmList?kfsid=4407050397&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门博富置地发展有限公司</a>","江门市新会区会城街道文华路与明德路交叉口的西北角地块","新会区"]},{"id":"6","data":["江门市新会区会城文华路10号海悦天铸华苑1座","<a href=\"/public/web/ysxm_JM?ysxmid=D70EB8269FA04F20A119A4C4F729E8BF&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">海悦天铸华苑</a>","<a href=\"/public/web/Yszxx?ysxmid=D70EB8269FA04F20A119A4C4F729E8BF&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020004号</a>","<a href=\"/public/web/KfxmList?kfsid=440705133587&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市新会区新隆置业发展有限公司</a>","海悦天铸华苑","新会区"]},{"id":"7","data":["江门市新会区会城今华路32号碧水轩8座","<a href=\"/public/web/ysxm_JM?ysxmid=6AD49955CBB443FA80C382338E7BBBC5&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">碧水轩</a>","<a href=\"/public/web/Yszxx?ysxmid=6AD49955CBB443FA80C382338E7BBBC5&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020003号</a>","<a href=\"/public/web/KfxmList?kfsid=4407050403&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市新会区高盛装饰工程有限公司</a>","江门市新会区会城今华路32号","新会区"]},{"id":"8","data":["江门市新会区会城今华路32号碧水轩7座","<a href=\"/public/web/ysxm_JM?ysxmid=F87AD333F20F46FFA968EA6B4491A832&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">碧水轩</a>","<a href=\"/public/web/Yszxx?ysxmid=F87AD333F20F46FFA968EA6B4491A832&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020002号</a>","<a href=\"/public/web/KfxmList?kfsid=4407050403&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市新会区高盛装饰工程有限公司</a>","江门市新会区会城今华路32号","新会区"]},{"id":"9","data":["江门市新会区会城潮江路20号御锦世家花园8座","<a href=\"/public/web/ysxm_JM?ysxmid=DA2BA7634FB64BF9B6D438D73ECF5684&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">御锦世家花园</a>","<a href=\"/public/web/Yszxx?ysxmid=DA2BA7634FB64BF9B6D438D73ECF5684&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020001号</a>","<a href=\"/public/web/KfxmList?kfsid=4407050404&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市新会区诚恩置业发展有限公司</a>","江门市新会区会城城东通天埠(土名)","新会区"]},{"id":"10","data":["江门市新会区会城同安路2号骏凯豪庭半岛二街1座-9座、11座、13座-15座","<a href=\"/public/web/ysxm_JM?ysxmid=FCC5D71FE4FA42AC8B7CD353B1A73D78&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门新会骏凯豪庭</a>","<a href=\"/public/web/Yszxx?ysxmid=FCC5D71FE4FA42AC8B7CD353B1A73D78&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2019122号</a>","<a href=\"/public/web/KfxmList?kfsid=440705133186&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市骏凯豪庭开发建设有限公司</a>","江门市新会区会城银港大道65号骏凯豪庭御海1座","新会区"]}]}}

可以看到,键名为 Suceed 的字符串对应的值是 "1" 也是一个字符,键名为 Message 的字符串对应的值是"成功"字符串,而 Data 跟着的是一个字典对象,其中也是若干个键值对。由这例子我们可以看出,json 就是键值对嵌套的一种结构。然后在 python 中有一个内置的库,名字也叫做 json,提供了两个常用的方法来处理这类对象。

json.loads

       json.loads 方法可以将一个 json 字符串转化成字典,然后方便我们按键值对的方式去处理。

json.dumps

      json.dumps 方法则是一个反操作,将 python 的一个字典对象转成 json 字符串。

      在我们爬取到的数据中,Data 中的 rows 字段保存了我们所要的信息,以其中的一个对象为例如下。

{"id":"1","data":["江门市新会区会城梅江南路22号海棠公馆1座","<a href=\"/public/web/ysxm_JM?ysxmid=635FD571C35C412E85E67BC85A854B73&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">海棠公馆</a>","<a href=\"/public/web/Yszxx?ysxmid=635FD571C35C412E85E67BC85A854B73&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">新会预许字第2020009号</a>","<a href=\"/public/web/KfxmList?kfsid=4407050408&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市美溢房地产开发有限公司</a>","枢纽新城今洲路南侧、规划梅江南路东侧地块","新会区"]}

        可以看到,其中的 data 中包含有一些 html 格式的字段,我们的目标就是提取其中的元素。如果像上面的例子中,直接使用 json.loads 这个函数,确实没什么问题,因为其中没有什么可能引发歧义的东西。另外可以看到,上述例子中使用了转义字符 \ 左斜杠,左斜杠使得后续的符号被理解成字符串的一部分而不是一个终结。但是我们遇到的问题就是其中含有转义字符时,使用这个函数会报错。

{"id":"472","data":["","<a href=\"/public/web/ysxm_JM?ysxmid=7C92E86EF83E46488897A205899F9A22&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">珑城半山低层住宅B区B3型136\137\138\139幢</a>","<a href=\"/public/web/Yszxx?ysxmid=7C92E86EF83E46488897A205899F9A22&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">2016094</a>","<a href=\"/public/web/KfxmList?kfsid=440705-133525&jgid=d111693f-6943-4f13-858a-cd61ff9184fd\" target=\"_blank\">江门市众力房地产有限公司</a>","新会区会城大道28号珑城半山","新会区"]}

例如这个,其中将转义字符\出现在了不恰当的位置,导致解析错误。那么要如何解决这个问题呢?想了两天没有什么特别好的思路,只能绕开这个问题,既然是字符串,那我就用正则表达式来处理着 json.loads 无法解决的问题不就可以了吗,惹不起我还躲不起吗?

 

 

 

 

 

 

 

 

 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!