全球python开发论坛

125次阅读

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

最近有个需求,就是按照搜索关键字然后爬取国内某个网站的图片并发送到 TG bot,现在遇到了一个问题,就是这个站点用的图床是一个叫做 imgsto 的图床,这个图床有一个恶心的地方就是点进去之后他会叫你点击一个叫做 Continue to image 的按钮(这个按钮要点好几次才可以点到),这个简单,我就撸了几行 python 代码获取真实链接
全球 python 开发论坛
全球 python 开发论坛
然后把这个链接发给 TG bot 的时候死活得到 400 的结果,最后经过测试发现,这个返回来的链接好像时关联访问 IP 的,当我使用其他 IP 来访问这个我得到的 real_url 时会得到一个 Wrong IP 的结果
全球 python 开发论坛
现在我想问的是,要怎么按照原来的设想,我输入关键字之后脚本自动把这张图发送到 bot 呢?
我目前自己想的一个方法就是先把这个图片解析完之后下载到本地,然后再本地上传到 TG 服务器,但是这样每一张图都涉及到一次 IO 操作
有没有什么办法避免呢? 比如存到内存之类的 (可以吗?) 这样就不用一直往复写入硬盘了
或者说各位 MJJ 有没有其他更优雅的方式?
得到六楼提醒,直接使用 request 的 content 对象解决了多次操作 IO 问题

requests 的 content 是二进制流,本来就是存在内存中的,可以直接使用,但是这样有很大弊端,有可能内存溢出,最优解还是将 content 写入文件,形成类似文件池,单独进程去处理文件池发给 bot 图片漏点了和你想法一样,下载再上传,其实效率上也没有太大变化,毕竟 tg 的 api 也有限制的只能下载在上传然后删除文件带上本地 cookie 试试,太久没写爬虫了
已经三年没写过 py 了
都寄吧忘了 IO 操作影响不大,不过你也可以试试直接用 requests.get 来请求这个图片的地址,然后返回值里面好像有个 content 成员可以直接使用种子的预览图片???Redis,直接在内存处理了啊

hihandbag 发表于 2022-5-7 21:50
种子的预览图片???

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

Floppy 发表于 2022-5-7 21:42
IO 操作影响不大,不过你也可以试试直接用 requests.get 来请求这个图片的地址,然后返回值里面好像有个 conten …

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

Salta 发表于 2022-5-7 21:55
Redis,直接在内存处理了啊

虽然问题解决了,但是我还是想请教一下,怎么处理?因为我记得好像 redis 只能存放字符串 哈希 集合 列表呀,还能存文件的吗 requests 的 content 是二进制流,本来就是存在内存中的,可以直接使用,但是这样有很大弊端,有可能内存溢出,最优解还是将 content 写入文件,形成类似文件池,单独进程去处理文件池发给 bot 有个更通用一些的方法,把内存映射成硬盘,然后下载的文件直接写入这个内存盘好久没看到那么有技术含量的帖子了,我最近也有个类似的问题,图片要 post 过去才能拿到,不是地址,而是直接返回二进制文件,也是 python 搞定的。

rem 发表于 2022-5-7 22:25
requests 的 content 是二进制流,本来就是存在内存中的,可以直接使用,但是这样有很大弊端,有可能内存溢出 …

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

phpsky 发表于 2022-5-7 22:33
好久没看到那么有技术含量的帖子了,我最近也有个类似的问题,图片要 post 过去才能拿到,不是地址,而是直接 …

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

深海空间 发表于 2022-5-7 22:38
对原理性的不是很理解,我想问下,像下面这样,第一次把文件请求下来之后的 content 存在变量 file 里,然后 …

import gc
file = …
……
del file
gc.collect()

深海空间 发表于 2022-5-7 22:38
对原理性的不是很理解,我想问下,像下面这样,第一次把文件请求下来之后的 content 存在变量 file 里,然后 …

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

rem 发表于 2022-5-7 22:57
按你的想法是单线程运行,函数执行结束会会回收内存,这样不存在内存问题,就是效率比较低。更多的是网络 …

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

深海空间 发表于 2022-5-7 22:09
虽然问题解决了,但是我还是想请教一下,怎么处理?因为我记得好像 redis 只能存放字符串 哈希 集合 列表呀 …

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

goyz 发表于 2022-5-7 23:22
看数据量有多大,对时延要求有多高,机器内存有多少,没必要过度设计。
多线程也不一定就能快,本身 python …

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

深海空间 发表于 2022-5-8 00:07
其实我这个程序设计并不是特别严谨的,如果因为网络问题导致的 get/post 失败,那我就 try 完之后把本次 reque …

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

goyz 发表于 2022-5-8 00:16
程序设计上丢不丢弃都无关正确性,主要还是看你的需求了,采取不同的失败处理策略,失败即停,失败忽略,…

好的,多谢啦解决不了 楼下会

goyz 发表于 2022-5-8 00:16
程序设计上丢不丢弃都无关正确性,主要还是看你的需求了,采取不同的失败处理策略,失败即停,失败忽略,…

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

深海空间 发表于 2022-5-7 23:07
好吧,那我再问下,每一张图片都要执行这三个步骤,get 下来写入保存到本地,在读取出来发送给 TG,再删除 …

读写文件都需要时间和 io,不考虑持久化的问题可以直接利用 requests 对象的 content 二进制数据,内存效率最高。没有持久化脚本不出问题还好,遇到个没有捕获的异常,内存里的数据都没啦,重新爬?
实践出真知,遇到问题解决问题直接把内存挂载成内存盘,写入内存盘中做临时文件不就行了。

rem 发表于 2022-5-8 13:37
读写文件都需要时间和 io,不考虑持久化的问题可以直接利用 requests 对象的 content 二进制数据,内存效率最 …

不需要持久化,程序的处理流程就是,tg 用户发送关键字 –>vps 收到关键字 –>python 拿着关键字去某网站搜索并获取到图片 –> 将图片用 tg api 发送给用户。本地不做任何储存。假如以上流程中间一环捕获到任何异常,直接停止本次查询,然后等待服务端发送过来下一个关键字

深海空间 发表于 2022-5-8 14:43
不需要持久化,程序的处理流程就是,tg 用户发送关键字 –>vps 收到关键字 –>python 拿着关键字去某网站搜索 …

我以为爬整个网站。你这不需要落盘

正文完
 0