懒,求个异步爬虫,必要需求是方便处理异常

2020-05-11 14:10:53 +08:00
 imn1
速度、并发量不是最大需求,当然能做到更好

必要的是出现爬取失败的 url,能扔进队列重试若干次
持续失败( 403/404/50x,超时……等等)的能记录下来

其次是可以自定义 header,包括 cookies 、UA 等等,当然包括可重用(session)

搜了好几个简述都没这方面说明,估计不是逐个看文档,就是看代码……
谁知道有这样的,省我一点时间,谢了
2673 次点击
所在节点    Python
16 条回复
NaVient
2020-05-11 14:21:35 +08:00
开源不是伸手,别人没实现的你可以实现了提 PR 方便下一个朋友
also24
2020-05-11 14:30:22 +08:00
第一行和第三行需求,直接 aiohttp 不就好了。

第二行需求,自己用 redis 实现一下估计也就一百行以内?
dayeye2006199
2020-05-11 14:35:09 +08:00
这是传说中的伸手党?
imn1
2020-05-11 14:52:18 +08:00
@also24
redis 我只认识这五个字母,🐶

@NaVient
伸手是伸手,但也不完全是拿来就用,肯定要自己改的
只是年纪大了,又不是用来吃饭的东西,总不能我现在对某个软件不满意就重写一个,能尽量少改动最好

爬虫十多年前就写过,单线程,但我较强能力在 parse (韩文以前我都爬过百多个站点),aio 或多线程方面很弱
我以前玩的是 aria2 抓取,然后脚本 parse 出 link,导出 aria2 list,再重复几次到最后完成
以前这样玩好处是主动操作,满足感强,现在只想扔到后台爬完整理就算了
ruby0906
2020-05-11 15:14:56 +08:00
要不是轮子太多,看楼主的描述我都想自己写一个。
imn1
2020-05-11 15:23:01 +08:00
@ruby0906 #5
就是这个意思,如果自认为能力足够,已经动手了,我就从来没用过别人的 html parser 轮子
问题是自己写出来的,自己用着都觉得糟心,还不如用人家高水平的轮子
ClericPy
2020-05-11 15:51:45 +08:00
以前还真写过类似的... https://github.com/ClericPy/torequests

支持协程, 线程, 同步, 异步, 反正就是当年想在同步环境里享受到协程的高性能用的

和原生 aiohttp 比, 损失 10% 性能, 带上 uvloop 损失 15% ~ 20%... 损失这么多现在我都有点不想用它了...

https://paste.ubuntu.com/p/fFWsNmvVX2/ 简单的小例子
tlemar
2020-05-11 16:11:11 +08:00
scrapy 可以满足需求
imn1
2020-05-11 16:16:15 +08:00
@ClericPy #7
哎呀,失敬失敬,刚刚在看 torequests,没想到下一秒作者就出现了

既然大驾光临,顺便问两个问题:
1.我写个 class 继承 FailureException,就可以自行处理了吧,error 是 http error code 么?
超时的 error 是什么,文档好像没写这个
2.自定义 header 好像只见到 torequests.utils.curlparse(string, encoding='utf-8') ?
ClericPy
2020-05-11 16:36:46 +08:00
@imn1 #9

1. FailureException 其实就是在 catch exception 的时候不抛错, 让它 Return 回来方便自省和排查, FailureException.error 实际就是原始抛出的错误

另一方面 FailureException 主要作用就是存放了 request 的 kwargs, 方便回调的时候用上

超时根据不同的依赖不一定是什么 error, 需要根据依赖来判断, aiohttp 或者 requests 里面都有很多细分, 超时也是区分了读超时和连接超时的, 所以得自己去他们源码里看看, 比如 requests.exceptions 里的 Timeout ConnectTimeout ReadTimeout, aiohttp 里面更复杂

因此, 这里面的重试的涵盖范围默认是 aiohttp 和 requests 里面的请求错误的基类, 避免 handle 一些非请求类错误 (早年间因为 handle 了 KeyboardInterrupt 导致我一个十万请求的脚本差点停不下来...

2. 没看懂自定义 Headers 是什么需求, 有个例子么. 可重用 Session 是默认的, tPool Requests 类都是只用一个 Client Session

3. 代码一开始是刚上班时候自己边学边折腾的, 实际没什么有价值的地方, 不如自己现写一个 wrapper...
imn1
2020-05-11 16:56:31 +08:00
@ClericPy #10
自定义 header,例如 UA 用 firefox/chrome...,cookies 增加一些条文,如页面访问点击“同意”,cookies 会多了 agree=1 这样,程序首次访问 cookies 没有这条或者 agree=0,后面用代码添加上去才能访问后面的页面

我本来是想 requests 写个单函数,然后多进程执行,感觉放后台跑有点重,所以才找找有什么异步协程的,这样静默运行不影响我干其他事,所以能记录下载失败反而是最关键的
crella
2020-05-11 17:02:38 +08:00
楼主自己的 html parser 的其中比较好的几个可以给个链接吗?想看看是怎么解析 html 的。谢谢
ClericPy
2020-05-11 17:08:49 +08:00
@imn1 #11 这些自然是带的, torequests 要做的就是兼容 Requests 的参数...

req = tPool()
task = req.get('http://httpbin.org', headers={"Cookie": "agree=0;"})
resp = task.x

这些都是 Requests 库原生的参数

记录下载失败, 拿到结果以后如果是错误, FailureException 对象的 bool 都是 false 的, 而且也有 self.ok 来兼容 Requests 的响应, 所以只要判断 self.ok 就能知道请求是否成功了. Requests 的 Response.ok 判断的好像是状态码在 range(200, 300) 之间

记录下载失败, 写个 Callback 函数做变量塞上应该就够了, lambda r: r.ok or open('file.txt', 'a').write('xxx')
imn1
2020-05-11 17:34:09 +08:00
@crella #12
没公布,而且有些年头,这次也要重写
没什么特别,就是正则用得好而已(我不需要 bs4/lxml )
加两三个函数,可以根据捕获"last page"生成一个组合 list,也就是 itertools.product()之类
有个函数是处理,分散在几个页面的信息,要各自取出合成一个 record,外面的框架很少见有做这个,但这个只是业务逻辑理顺,跟代码能力无关
可以导出 aria2/wget 可用的 list,wget 不能指定输出文件名,加个下载后对照改名的脚本
……

总的一句,就是做了一个 py,然后不同站点写个 ini/cfg/yaml 什么的,把一堆正则、referrer 按顺序扔进去,就能跑,仅此而已,没什么特别,比别人强的地方可能就是我熟悉中日韩 unicode 字符,文字处理比人家写的要简洁顺手些
neoblackcap
2020-05-11 17:35:08 +08:00
@crella 解析 html ?你去看看 nginx 的不就结了。基本上都是拿 nginx 的代码改一下。要不然你去看 pichttpparser 也可以,不过那个到底有多标准,我不好说了。nginx 解析 html 的代码好像也就一个文件,非常短小精悍
triangle111
2020-05-12 11:58:06 +08:00
有个开源的 Ruia,也是异步爬虫,就是插件没人开发。LZ 说的这些功能刚好都有

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/670525

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX