在进行数据分析以及竞品调研的时候, 首先需要明确, 最基础也是最关键的一个步骤, 就是必须把数据从网络上面抓取下来。而在整个过程中里最常用的两个 HTTP 库是同步的和异步的这两个(具体的库名称可能需要读者自行对应上下文填补空缺), 这两者加在一起就足以完美覆盖绝大部分的应用场景。
技术本身是一种中性的工具。你务必要遵守目标网站的规定, 处理.txt格式的内容, 控制请求的频率, 不要去爬取付费与私有的内容, 做到合规使用。
一、:最优雅的 HTTP 库
被称为 "HTTP for ",一行代码就能发起请求:
import requestsresp = requests.get('https://httpbin.org/get')
print(resp.json())
关于GET这种请求方式, 还有它所需要的那些参数。
# 基本请求resp = requests.get('https://httpbin.org/get', timeout=10)
print(resp.status_code) # 200
# 带参数请求
params = {'page': 1, 'per_page': 5, 'search': 'python教程'}
resp = requests.get('https://httpbin.org/get', params=params)
用户使用的是 POST 这个方式来完成数据的提交操作。
# JSONresp = requests.post('https://httpbin.org/post',
json={'username': 'test', 'action': 'login'})
# 表单
resp = requests.post('https://httpbin.org/post',
data={'username': 'test', 'password': 'secret'})
# 文件上传
resp = requests.post('https://httpbin.org/post',
files={'file': open('doc.pdf', 'rb')})
要维持那个登录的状态。
能够在多次的进行请求的这个过程当中, 保持那种状态, 因此它就相当于是适合需要那个登录状态的这种场景的。
session = requests.Session()session.headers.update({'User-Agent': 'MyBot/1.0'})
session.get('https://httpbin.org/cookies/set/session_id/abc123')
resp = session.get('https://httpbin.org/cookies')
print(resp.json().get('cookies')) # {'session_id': 'abc123'}
超时、重试、异常处理
from requests.adapters import HTTPAdapterfrom urllib3.util.retry import Retry
# 超时
resp = requests.get(url, timeout=(3, 10))
# 自动重试
session = requests.Session()
retry = Retry(total=3, backoff_factor=1,
status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount('https://', adapter)
养成一个好习惯, 就是请求要统一来做异常捕获, 这里需要加上//, 遇到429这个状态码的时候要降频, 遇到5xx这类错误的时候要稍后重试, 这样可以避免程序崩溃。
二、把相关的请求同时安排出去, 让它们一起去发送。
同步请求的方式是逐个地、一个一个地按照顺序去发送, 所以说如果是执行 5 个 URL, 那么它整体所消耗的时间就是这 5 个 URL 各自的耗时加起来得到的总和。
异步并行的机制则完全不同, 整个流程处理完毕大概只需要花费的时间只和最慢那一个请求所需要的时间差不多, 因此在那些需要并发处理的场景下面, 这种方式所带来的加速效果通常能够达到好几倍的程度。
import aiohttpimport asyncio
async def fetch(session, url):
async with session.get(url) as resp:
return await resp.text()
async def fetch_all(urls):
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
return await asyncio.gather(*tasks)
urls = ['https://httpbin.org/get'] * 10
results = asyncio.run(fetch_all(urls))
选择方案的简明指南是, 对于请求数量较少或者属于普通水平的情况使用前者, 而对于并发请求数量达到成百上千的高强度使用情况则使用后者的方案。
三、小结
要是这篇内容能对你有所帮助的话, 那希望你能够去点赞和收藏, 并且继续关注我, 因为我会不断地进行输出, 来提供那些在实干中具有价值的内容与干货知识。而在接下来的这一篇文章当中呢, 主要会涉及到的主题是有关“+”这样的内容, 重点在于如何搞定网页解析方面的那些事儿。