python 使用 lru_cache 缓存代理IP
本文地址:https://www.cnblogs.com/tujia/p/13690973.html
背景:当我们用python写爬虫时,一般会用到代理IP;代理IP一般是有一定有效时间的,每次请求都换IP,有点浪费IP,所以我们需求在IP的有效时间内需要缓存IP,不换IP
前提知识:
1)@lru_cache 装饰器可以在程序运行期间缓存函数返回值,第一次调用函数缓存函数返回值,后面的调用就直接读缓存返回
2)@lru_cache 装饰器会为被装饰的函数创建两个属性(方法):cache_info 和 cache_clear,其中 cache_clear 方法可以清除缓存,重新计算函数
3)了解更多,请看官方文档:https://docs.python.org/zh-cn/3.7/library/functools.html#functools.lru_cache
下面就直接上代码了,红色的地方是重点:
import requests from bs4 import BeautifulSoup from functools import lru_cache # 获取代理ip(可以去芝麻代理注册一个账号,领取免费IP) # @link http://h.zhimaruanjian.com/getapi/ @lru_cache(maxsize=1) def getProxies(retry_times=0): # 直连IP的api地址 api_url = 'http://webapi.http.zhimacangku.com/getip?num=1&type=1&pro=&city=0&yys=0&port=1&pack=97108&ts=0&ys=0&cs=0&lb=1&sb=0&pb=4&mr=1®ions=' # 请求头 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'} try: r = requests.get(api_url, headers=headers, timeout=3) if r.status_code == 200: if r.text.find('{') > -1: j = r.json() # 请x秒后再试 if j['code'] == 111: s = int(re.search(r'\d', j['msg']).group(0)) time.sleep(s) # 套餐已用完 elif j['code'] == 121: return None else: proxyMeta = 'http://' + r.text.strip() return {'http': proxyMeta, 'https': proxyMeta} if retry_times < 3: retry_times += 1 return getProxies(retry_times) except requests.exceptions.RequestException: pass if retry_times < 3: retry_times += 1 return getProxies(retry_times) else: return None # 获取网页内容 def getContent(url, retry_times=0, use_proxy=True): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'} try: proxies = getProxies() if use_proxy else None r = requests.get(url, headers=headers, proxies=proxies, timeout=10) if r.status_code == 200: r.encoding = 'utf-8' return r.text except requests.exceptions.InvalidProxyURL: print('InvalidProxyURL: %s' % str(proxies)) # 代理异常,清除一下代理缓存,重新获取代理ip getProxies.cache_clear() except requests.exceptions.ProxyError: print('ProxyError: %s' % str(proxies)) # 代理异常,清除一下代理缓存,重新获取代理ip getProxies.cache_clear() except requests.exceptions.InvalidURL: print('InvalidURL: %s %s' % (url, str(proxies))) # URL错误,也有可能是因为代理异常,所以也重新获取一个代理ip getProxies.cache_clear() except requests.exceptions.Timeout: print('TimeoutError: %s' % url) except requests.exceptions.RequestException: print('RequestException: %s' % url) # 代理异常或其他异常时 if retry_times < 3: retry_times += 1 return getContent(url, retry_times, use_proxy) else: return '' if __name__ == '__main__': for i in range(3): # 看一下三次打印的代理ip是不是一样的 print(getProxies()) # 请求一下百度试试 content = getContent('https://www.baidu.com') if content != '': soup = BeautifulSoup(content, 'lxml') print(soup.title.string) print('Finished')
本文地址:https://www.cnblogs.com/tujia/p/13690973.html
完。