全球python开发论坛

76次阅读

共计 2232 个字符,预计需要花费 6 分钟才能阅读完成。

最近有个需求,就是按照搜索关键字然后爬取国内某个网站的图片并发送到 TG bot,现在遇到了一个问题,就是这个站点用的图床是一个叫做 imgsto 的图床,这个图床有一个恶心的地方就是点进去之后他会叫你点击一个叫做 Continue to image 的按钮(这个按钮要点好几次才可以点到),这个简单,我就撸了几行 python 代码获取真实链接

然后把这个链接发给 TG bot 的时候死活得到 400 的结果,最后经过测试发现,这个返回来的链接好像时关联访问 IP 的,当我使用其他 IP 来访问这个我得到的 real_url 时会得到一个 Wrong IP 的结果

现在我想问的是,要怎么按照原来的设想,我输入关键字之后脚本自动把这张图发送到 bot 呢?
我目前自己想的一个方法就是先把这个图片解析完之后下载到本地,然后再本地上传到 TG 服务器,但是这样每一张图都涉及到一次 IO 操作
有没有什么办法避免呢? 比如存到内存之类的(可以吗?) 这样就不用一直往复写入硬盘了
或者说各位 MJJ 有没有其他更优雅的方式?

得到六楼提醒,直接使用 request 的 content 对象解决了多次操作 IO 问题

网友回复:

注册 requests 的 content 是二进制流,本来就是存在内存中的,可以直接使用,但是这样有很大弊端,有可能内存溢出,最优解还是将 content 写入文件,形成类似文件池,单独进程去处理文件池发给 bot

深海空间 图片漏点了

rem 和你想法一样,下载再上传,其实效率上也没有太大变化,毕竟 tg 的 api 也有限制的

表妹 只能下载在上传然后删除文件

深海空间 带上本地 cookie 试试,太久没写爬虫了 已经三年没写过 py 了 都寄吧忘了

etc 小号 IO 操作影响不大,不过你也可以试试直接用 requests.get 来请求这个图片的地址,然后返回值里面好像有个 content 成员可以直接使用

雁过拔毛的 MJJ 种子的预览图片???

mjj 小号 Redis,直接在内存处理了啊

Floppy emmm, 咱现在讨论的是技术性问题

hihandbag 卧槽,还真可以,本来我的想法是把这个 requests 的 content 写入一个本地文件当中介,然后再读出来给 TG 的 api,没想到可以直接把这个 content 拿给 tg 使用,多谢多谢,这样就可以省下这些 IO 操作了

注册 虽然问题解决了,但是我还是想请教一下,怎么处理?因为我记得好像 redis 只能存放字符串 哈希 集合 列表呀,还能存文件的吗

注册 requests 的 content 是二进制流,本来就是存在内存中的,可以直接使用,但是这样有很大弊端,有可能内存溢出,最优解还是将 content 写入文件,形成类似文件池,单独进程去处理文件池发给 bot

深海空间 有个更通用一些的方法,把内存映射成硬盘,然后下载的文件直接写入这个内存盘

rem 好久没看到那么有技术含量的帖子了,我最近也有个类似的问题,图片要 post 过去才能拿到,不是地址,而是直接返回二进制文件,也是 python 搞定的。

橡树叶 对原理性的不是很理解,我想问下,像下面这样,第一次把文件请求下来之后的 content 存在变量 file 里,然后给第二次 requests 用,当第二次用完之后,那个 file 里存的 content 所占用的内存不是会被释放出来吗?还是会持续存在一段时间?如果会持续存在的话我可以手动删除吗?或者说把他存放再某个作用域里面,比如 for,我记得以前学 java 的时候好像记得,for 里定义的变量在结束循环之后会回收机制给回收?python 可以这样吗?

phpsky 我这个图床要 post 过去才可以拿到图片的 url,然后想拿到文件的话,还得重新 get 一次那个 post 取回来的链接

深海空间 import gc file = … …… del file gc.collect()

深海空间 按你的想法是单线程运行,函数执行结束会会回收内存,这样不存在内存问题,就是效率比较低。更多的是网络波动引起的问题,比如图片 get 正常,post 到 tg 出错,这个流程你怎么写是不是外面要套异常去跳过,或者图片 get 出错,你要重试吗,重试几次,重试过程进程是否锁死,这无疑是在浪费时间。所以我说的最优解就是做成生产者消费者的模式,一边只管获取图片写入文件,获取不到那是网络问题或者被反爬,文件有了另一边慢慢消费给 tg,成功一个删除一个或者移动到另一个文件夹再加上一定的保留期

goyz 好吧,那我再问下,每一张图片都要执行这三个步骤,get 下来写入保存到本地,在读取出来发送给 TG,再删除这个本地文件,这样会不会有性能问题? 到时候会加上多线程,因为 get 和 post 会需要一段时间,不能让脚本干等着。。

rem 二进制数据流就行 … 很简单,哈哈

注册 看数据量有多大,对时延要求有多高,机器内存有多少,没必要过度设计。多线程也不一定就能快,本身 python 是伪多线程,另外你这个是 IO 密集型,网络和磁盘 IO 有上限。

注册 其实我这个程序设计并不是特别严谨的,如果因为网络问题导致的 get/post 失败,那我就 try 完之后把本次 request 直接丢弃掉,这样会不会好点

goyz

深海空间 程序设计上丢不丢弃都无关正确性,主要还是看你的需求了,采取不同的失败处理策略,失败即停,失败忽略,失败重试,失败有限重试等等

goyz 好的,多谢啦

goyz 解决不了 楼下会

深海空间 主要是丢弃策略的话,应该可以防止我们前面提到的 request content(不打算写入硬盘本地文件)占用内存无法使用导致的内存不够的问题

正文完
 0