20210801爬虫学习记录

免责声明:个人学习与玩耍,切勿用于非法用途,请务必遵守robots协议,产生一切纠纷与本人无关。

0.关于Selenium,一个爬虫0基础菜狗的福音

因为一些原因摸上了爬虫玩玩,因为鄙人没有太多web基础,也就仅限于手写html的水平而已。所以刚开始玩发现用selenium+chrome这种直观的组合真的太友好了,在爬的过程中可以一步一步看自己的程序是如何走的。但是这种需要浏览器解析的操作毕竟太过于重量级,因此解析和系统占用都非常让人难受。在加载网页的过程中需要等待网页加载完,加载完后需要定位我们关注的内容并进行后续的处理(如保存下来)。而且多数情况下,我们需要的数据仅仅是网页里的或者链接里的一部分感兴趣信息,并不需要把整个网页都加载出来,因此使用request请求更好办一些。于是乎有了下面的故事。

1.关于requests

使用selenium面对动态加载的网页如果需要翻页还需要各种定位点击翻页的操作,十分头疼。因为操作来操作去,太恶心了。
打开网页后按f12查看所有的数据请求。或者使用抓包软件截取我们需要的网络请求。直接根据http后面的参数甚至可以一页获取我们需要的多页数据。甚至还可以猜参数搞到更多没有暴露出来的信息。有了url后,就可以直接requests get获得我们需要的数据,没有浏览器加载,极其高效。这里给个我的效率提升描述,并不对多数场景有效:使用selenium搞数据,同样一批数据,因为还需要time.sleep()等待网页解析加载,因此跑一轮需要5~6小时。而且,在DNS不给力的情况下,可能会更慢。由于我的IP为公网IP,因此,并不像运营商的私网用户那样直接走到目标机的私网服务器的,因此默认DNS是很慢的,需要指定DNS为:119.29.29.29或者114.114.114.114。(当然可能不是这个原因,但是经过我的实验确定个人用户的公网IP访问一般的网页确实变慢了,需要指定DNS才有好转)。当使用request直接GET时候,半个小时即能爬完所有数据。

2.关于多线程or多进程request

直接request我的网络占用大约200k~1M波动,(仅针对我的应用场景),而对我来说我的百兆乞59元丐版家庭光纤岂能满足?因此使用multiprocessing多进程做加速,跑满我龟速AMD cpu笔记本的全部逻辑核心。果然,在我Windows的笔记本上能够跑出来3M+的速度,我为什么使用多进程呢?因为python有GIL锁,不存在真正意义的多线程,所以我在数据相互独立、操作处理互不耦合的任务上选择多进程来加速。成功在Windows笔记本上2分钟跑完全部任务。
问题来了:
当我把程序放到Ubuntu的台式机上运行时,终端的显示变成了突然完成一把任务后假死不动,过了一会又冒出一堆完成的提示。htop看了一下好像同一时刻只有一个cpu核心在干活。看monitor里面的网络占用,就是一个尖尖后就平了,然后再一个尖尖的波浪。像极了我的selenium后面套上time.sleep()有人说Ubuntu的python多进程有点蠢,没有实际加速效果。刚开始我信了。我在win10子系统里试了一下,和Ubuntu的实体机表现一致。开始我以为是DNS的问题,改了发现并没有用,于是乎到处找能让Ubuntu真证跑起来多进程的方法。最终试了多种方法,发现效率都是一样的慢。偶然间,我想到会不会是GET就是IO操作,而IO比较慢,会引起线程阻塞,会不会是实际跑了多进程而阻塞掉了呢?我在多进程里直接搞死循环试一试。果然wsl(win10子系统)里面直接把cpu吃满了,也就是说实际跑了多进程的。那应该就是线程阻塞了但是Ubuntu唤醒不如Windows快而已喽?这样就解释的通为什么Ubuntu多进程卡卡的了。

3.Windows是不可能用Windows的,Ubuntu哥哥都是人才,说话又好听

有个东西叫:
import asyncio
import aiohttp
import nest_asyncio //这个好像是为了spyder能跑过,忘记了
协程!直接把阻塞的操作隐藏掉了,不需要占用很多cpu资源就可以干完爬虫多进程的活。
至此,一个2分钟能在Ubuntu干完我想干的活的小爬虫就完成了。另外我是一次把所有数据搞定在向磁盘写入。不得不说,向磁盘写入这个动作是真的慢,多进程也不行,直接回到了那个阻塞的老问题。其实后处理提取信息我更倾向于直接内存里做完,有磁盘参与的工作一定快不起来。
小发现:
aiohttp总不可能一直是成功的吧,万一你的url不对岂不是挂掉了?或者网络出了一点问题不是就挂掉了?健康的小软件一定是鲁棒的。因此我除了try except外,还想通过递归+递归计数的方式在爬失败的时候多尝试几次,但是我发现递归对于协程里的操作似乎不适用(递归不进去),因此我改成了:

while counter > 1:
	try:
		do_something_GET
		return XX
	except:
		counter = counter -1
		print(notify)
		return XX
print('fatal error')
return XX

20210801:03:52

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值