0%

一次爬虫实践遇到的问题

背景

​ 平时编写Blog的时候,使用了 sm.ms 的免费图床(┑( ̄。。 ̄)┍ 咳咳咳,这个名字不要误解,是一个正经的图片管理工具😂,如果访问流量比较少的,免费版本就可以满足需求), 后来想在本地也定时备份下所有的图片,以便后续更换图床做不时之需。 于是想到了爬虫去爬取已有的图片并下载到本地。

解决方案

最终通过调研,发现存在以下两种方式(欢迎提出其他解决方案):

方案一:BeautifulSoup 爬虫

优点:可指定获取特定页面的 HTML 内容,然后通过解析 HTML 内容来获取所有图片的信息。

缺点:每次需要去更新请求中的 Cookie 信息来爬取对应的页面内容。

方案二: sm.ms API

优点:对外API接口中,/upload_history 接口返回了历史的上传记录,可以获取到所有的已上传的图片链接以及相关信息。

缺点:每次返回的是全量数据,这对于历史数据很多的用户,体验比较差。

遇到的问题

上面两种方案都试验过后实际都可以满足背景中的需求,但发现经过调试代码成功后,实际开始进行内容爬取的时候,直接请求报错。具体报错信息如下:

1
RemoteDisconnected('Remote end closed connection without response')

┑( ̄。。 ̄)┍ oh,比较坏的情况发生了,可能由于请求过快被服务端给拉黑了。。。通过后面的实验发现应该是被服务端封了IP

网上解决方案:使用User Agent和代理IP隐藏身份

但再使用网上的解决方案之前,存在一个比较怪异的现象,那就是同样的接口,使用本地的Postman却可以一直调用成功,使用本地的Pycharm脚本调用却一直失败。(都是通过API方式去调用的 /upload_history接口)

通过一系列的骚操作对比后,发现核心区别在于(postman自动使用了本地的代理端口去发送请求,也就是代理IP隐藏身份):
postman_proxy_1_new.png

Python requests 解决该问题的核心代码如下:

1
2
3
4
5
6
...
# 主要是添加 proxy 来隐藏实际自己的IP。
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: 如何判断自己的代理生效了可参考如下代码(参考链接):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import requests
from 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)
1
2
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 日本
------------- 本 文 结 束 感 谢 您 的 阅 读 -------------