Python爬虫初体验(3):线程锁,线程同步与异常问题的解决

前情提要:Python爬虫初体验(2):多线程的应用及爬取中的实际问题

从来没想过,写一个功能较为完备的爬虫代码,要花好几天的时间……

这次算是增长了许多编程经验。


好的废话不多说,进入正题

上次的代码中,由于部分XKCD漫画有特殊格式(还有 404 彩蛋),而我的代码中 try-except 结构只处理了连接超时的问题,没有对漫画本身的格式变化进行处理,导致线程意外中断。虽然最后写了重试下载,但是它和上面的一样,有个致命问题:如果是漫画格式的问题,它会陷入无限死循环。

所以这次对以上问题进行了规避式处理:将所有步骤写进 try 里面。并且,代码仍然采用重试机制,如果重试仍然有错误出现,那么记录这个漫画编号,程序运行结束后手动下载这些特殊的漫画。

……

那么这次的新知识,就是所谓的线程锁和线程同步。

线程锁:使用 mutex = threading.Lock() 将线程锁的变量赋值给 mutex,之后在 mutex 中分别用 acquire() 和 release() 方法来上锁/解锁。这样做是为了避免几个线程同时访问变量造成混乱。

调用 acquire() 后,接下来代码中的变量将只能由当前线程访问,其余线程会被阻塞,直到使用 release(),其余线程才能访问这些变量。例如,我要对全局变量 count 进行读取和 +1 操作,不上锁时,可能第 1,2 个线程在 +1 时,第 3,4 个线程在读取,就会造成数据不统一的问题。所以这种情况一定要上锁确保访问安全。

线程同步:如果我们希望子线程全部结束后,能继续执行主线程,那么需要用到 join() 方法。

def func_1():
    # do something_1

thread_list = []
for i in range(5):
    thread_list.append(threading.Thread(target=func_1))
    thread_list[i].start()

for i in range(5):
    thread_list[i].join()

# do something_2

对于线程 t,调用 t.join() 使得主线程在这个线程执行完之后才继续进行下一步操作。

(知识参考了liudemeng:Python中线程与互斥锁这篇文章)

然后!

还是一样的方法去搞……

哎。几天下来都没弄好,不知道这次又会怎样……

……

果然还是出问题了qwq

前两个线程倒是下载完了,后面三个线程居然在中途全部卡死,这是什么意思???

最后一直卡在 874 号漫画上……然后就没动静了……

……

经过我一番分析,原来有一行下载的代码写的是

picres = requests.get("http:" + picurl)

第一次写爬虫的时候就提到了:不能直接使用 requests.get(),以防超时卡死!!!

这里疏忽了没有改,导致后三个线程下载中途均出现了 Read Timeout(读取超时)然后卡死的现象

然后一直卡在那里,程序就这样 GG 咯 (0.0)\\

……


哎!第四次了。这次应该会成功吧。

为了加快速度,把线程数从 5 改成了 6;为了得到不能批量下载的漫画编号,最后记录了一个 log 文件,记下了编号和总耗时。

……

……

Nice,这次的程序终于没问题了!并且几个特殊漫画的编号也保存了下来

最后看到,耗时接近 1 小时;2173张/h 的速度,相比于原来 300张/h (50张漫画 10分钟)的速度要提高了不少。一个是因为启用了多线程,另一个是读取超时的时间从原来的 10s 变为了 4s。


简单总结一下。

这次的爬虫体验收获还是很大,不仅是学到的知识得到了运用,同时发现了许多新的问题,特别是之前没有考虑过的问题:例如读取超时的处理,错误类型的判断,错误的处理,意外发生时的应对策略,等等。

于是,耗时 5 天的这个爬虫终于走到了一个新的里程碑处。开心!

下一步,可以再深挖一下多线程的应用,也可以开始准备图像处理的练习了。事情还是很多的。

……

最近生活上还需要多多调整心态。可以想想那些比我强的同学是怎么做的。

……

今天又拖到了 11 点过,说好的 11 点睡觉呢!!

不说了赶紧滚去睡觉~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值