2018年七月二十五号bug总结

1、为什么json.load出来的数据顺序和之前的不一样
进行json_code之前的数组有排序或者有key值  json数据会自动根据key进行排序 所以要想json跟数组顺序一致 要进行 array_values处理 即是变成索引数组 
对json对象进行遍历可以用. 或者[]

2.url中带有callback=xxx会对返回的json数据有影响,解析的时候去掉url中的callback

3.with open('movie.jsonline', 'a', encoding='utf8') as f:
window下默认文件的解码格式GBK,而写入的时候用的是utf-8,需要指定文件编码格式

4.将多行json保存为json文件报错
解决方法:保存为jsonline格式

5.对于贴吧的数据,用xpath获取不到

贴吧网页中的代码实际上是被注释过的,推测:1、真正实现页面功能元素被藏在json中;2、代码加载完后有json实现了注释功能。

解决方法有三种:
(1)需要用正则抓取
(2)或者直接解开注释
html_new = response.content.decode().replace(r'<!--', '"').replace(r'-->', '"')
html_new = html_new.encode()
(3)遇到这种情况,可以试下用旧的浏览器请求头,返回的页面就不是这种把内容藏在注释里面的

6、用正则爬取网页的时候,需要先去掉空格,需要去掉多余的部分
dz = re.sub("&ldquo;|&rdquo;", "\"", div)
dz = re.sub("<p>|<br />|</p>|\s","", dz)
dz = re.sub("&hellip;", "...", dz)

7.在运行多进程的时候报错
The "freeze_support()" line can be omitted if the program
is not going to be frozen to produce an executable.

原因:貌似是window特有的一个问题,原因不明
解决方法:
把进程相关代码放到if __name__ == '__main__':下

8.多进程无法封装到装饰器中使用死循环
这个跟multiprocessing的原理有关,也涉及到Python中pickling的一些实现机制。

首先要说明multiprocessing模块现在有多种实现原理,类Unix系统默认使用fork,原理在于创建Process并启动的时候进行一次fork,然后子进程执行Process中指定的函数,它可以继承创建进程时内存中的对象,因此可以指定各种对象给子进程如函数、闭包、socket等

而Python2中Windows操作系统的实现spawn,每次重新启动一个全新的Python进程。以及Python3中forkserver的实现(在multiprocessing初始化的时候通过fork创建一个forkserver的进程,forkserver进程不再执行后续的代码,而是等待请求;所有后续创建multiprocessing进程时,都连接forkserver,由forkserver进行fork,产生一个“干净”的进程来作为新进程),这两种实现并不继承当前运行环境中的对象,所以需要使用的对象必须通过pickling的方法传递给子进程。

另外,multiprocessing中的Pool对象,它的原理在于预先创建好许多进程,然后从主进程中接受任务。这些任务因为不是在创建进程(fork)时创建出的,所以必须通过pickling的机制传递给子进程。multiprocessing.Queue和multiprocessing.Pipe也同样是使用pickling模块在进程间传递Python对象。

接下来就要说一下pickling了,pickling模块可以将Python对象序列化成字节流,再反序列化回到Python对象。但是它是有一定限制的,并不是所有的对象都可以进行序列化。函数和类在pickling中是不能“直接”序列化的,它们在pickling中序列化的原理在于将函数和类变为:package.module.func_name这样的字符串,即模块路径 + 函数/类名的形式。这就要求反序列化的时候:

这个模块可以被import

import后的这个模块中有这个全局名称

而且全局名称代表的值就是传递的值。

然而使用装饰器修饰的时候,main这个函数其实被修改了一次,变为了修饰之后的函数,但是未修饰的函数和修饰后的函数都共享了__main__.main这个名称,这导致传递的虽然是修饰前的函数,但实际接收方接受了__main__.main这个名称,然后重新import得到的是修饰后的函数,所以在子进程中执行的也是修饰后的函数。multiprocessing模块有个安全机制,禁止在multiprocessing创建的子进程中再创建multiprocessing子进程,因此这个修饰过的函数会在.Pool的地方报错,这个异常没有传递回主进程,所以看上去就像什么都没有做一样。作者:灵剑来源:知乎

解决方法:
老老实实手动将函数源代码改写
 

猜你喜欢

转载自blog.csdn.net/m0_38106113/article/details/81208986