背景
    平时编写Blog的时候,使用了 sm.ms 的免费图床(┑( ̄。。 ̄)┍ 咳咳咳,这个名字不要误解,是一个正经的图片管理工具😂,如果访问流量比较少的,免费版本就可以满足需求), 后来想在本地也定时备份下所有的图片,以便后续更换图床做不时之需。 于是想到了爬虫去爬取已有的图片并下载到本地。
解决方案
最终通过调研,发现存在以下两种方式(欢迎提出其他解决方案):
方案一:BeautifulSoup 爬虫
优点:可指定获取特定页面的 HTML 内容,然后通过解析 HTML 内容来获取所有图片的信息。
缺点:每次需要去更新请求中的 Cookie 信息来爬取对应的页面内容。
优点:对外API接口中,/upload_history 接口返回了历史的上传记录,可以获取到所有的已上传的图片链接以及相关信息。
缺点:每次返回的是全量数据,这对于历史数据很多的用户,体验比较差。
遇到的问题
上面两种方案都试验过后实际都可以满足背景中的需求,但发现经过调试代码成功后,实际开始进行内容爬取的时候,直接请求报错。具体报错信息如下:
| 1
 | RemoteDisconnected('Remote end closed connection without response')
 | 
┑( ̄。。 ̄)┍ oh,比较坏的情况发生了,可能由于请求过快被服务端给拉黑了。。。通过后面的实验发现应该是被服务端封了IP。
网上解决方案:使用User Agent和代理IP隐藏身份
但再使用网上的解决方案之前,存在一个比较怪异的现象,那就是同样的接口,使用本地的Postman却可以一直调用成功,使用本地的Pycharm脚本调用却一直失败。(都是通过API方式去调用的 /upload_history接口)
通过一系列的骚操作对比后,发现核心区别在于(postman自动使用了本地的代理端口去发送请求,也就是代理IP隐藏身份):

Python requests 解决该问题的核心代码如下:
| 12
 3
 4
 5
 6
 
 | ...
 proxy = {"http": "http://127.0.0.1:1235/", "https": "http://127.0.0.1:1235/"}
 res = requests.get(img_url,  headers=headers, proxies=proxy, stream=True)
 with open(file_path, "wb") as f:
 f.write(res.content)
 
 | 
PS: 如何判断自己的代理生效了可参考如下代码(参考链接):
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | import requestsfrom bs4 import BeautifulSoup
 
 def validate(proxies=None):
 https_url = 'https://ip.cn/api/index?ip=&type=0'
 http_url = 'http://ip111.cn/'
 headers = {'User-Agent': 'curl/7.29.0'}
 https_r = requests.get(https_url, headers=headers, proxies=proxies, timeout=10)
 http_r = requests.get(http_url, headers=headers, proxies=proxies, timeout=10)
 soup = BeautifulSoup(http_r.content, 'html.parser')
 result = soup.find(class_='card-body').get_text().strip().split('''\n''')[0]
 
 https_r_json = https_r.json()
 https_r_address, https_r_ip = https_r_json.get("address"), https_r_json.get("ip")
 with open("local_proxy.log", "a+") as f:
 f.write("=========================\n")
 f.write("访问https网站使用代理:%s %s\n" % (https_r_ip, https_r_address))
 f.write("访问http网站使用代理:%s\n" % result)
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 
 | validate()
 >> 访问https网站使用代理:172.69.34.243 美国 加利福尼亚
 >> 访问http网站使用代理:xxx.xxx.xx.xxx 中国 xx市
 
 
 >> 访问https网站使用代理:153.122.116.100 日本  东京都 东京
 >> 访问http网站使用代理:153.122.116.100 日本
 
 |