随便记录下写爬虫遇到的问题
记录编写爬虫中遇到的一些坑
- 或许会持续更新(咕咕咕)
- 遇到的问题会分类总结
使用的Python库
- requests:用于最基本的发送HTTP请求,包括get请求和post请求
- bs4:将获得的HTTP响应体进行格式化组织,从而能够进行多种检索
- re:对检索到的标签更细化地提取信息
- ThreadPoolExecutor, ProcessPoolExecutor:多线程与多进程,提高爬取速度
- 其他库:os、time等等,用于其他各种非主要用途
反爬虫绕过
请求头
- 一些网站会检测HTTP请求头里的信息,从而判断是否是爬虫访问。此时需要对请求头进行伪装。
- 使用浏览器自带的F12,查看每一次HTTP连接的请求头,复制到代码里并将其手动转换成字典形式的header
- 在使用requests发送请求时,带上参数headers=,
r=requests.get(url, headers=header)
;header必须是dict,这样可以在请求时带上给定的请求头
cookies
- 使用F12或者一些拦截工具burp等手动查看cookies,在使用requests发送请求时,带上参数cookies=
请求速度
- 过快的请求速度(明显超过一般浏览速度的请求)可能会被网站监测并被ban掉ip或是限制访问
- 使用
time.sleep(random.randint(a,b))
来暂停一个随机时间 使用IP代理,在requests请求时,带上参数proxies=proxy
,proxy应该是一个dict,形式为{'ip':'port'},可以有多个IP代理- 使用IP代理,在requests请求时,带上参数
proxies=proxy
,proxy应该是一个dict,形式为{'http':'ip:port', 'https':'ip:port'}
,分别为使用HTTP代理和HTTPs代理。
- 使用
字符编码问题
HTTP响应体的编码
- 自动化解决方案:
import requests
r = requests.get(url)
r.encoding = r.apparent_encoding
这种方法自动猜测可能的编码方式,并用这种编码方式编码响应体。但是猜测会存在一定的错误,自动选择编码方式会无法编码某些特殊的字符,比如简体中文、繁体中文
- 手动选择编码方式:
在请求到的html文件首部,一般会有对本文件编码方式的声明,例如<meta http-equiv='Content-Type' content='text/html; charset=gbk'>
里的charset字符集为gbk。此时,r.encoding='gbk'
就可以选择gbk编码
读写文件的编码
- Python文件默认的是unicode编码,有时候会出现unicode字符集无法编码一些特定字符,报unicode错误
- 在
open()
时,带上encoding=参数,指定编码方式encoding='utf-8'
,即可解决
- 在
网络问题
HTTPS验证
- 一些使用HTTPS的网站在访问时,需要进行HTTPS验证,可以在requests请求时指定
verify='\path\of\CAbundle'
参数来使用本地证书验证,也可以简单指定为verify=False
不进行验证 - 关掉验证后urllib3会报一个warning,使用
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
关掉这个警告
网络延迟重试
- 使用
requests.DEFAULT_RETRIES = 10
来修改requests库默认的重试次数,在网络状况不佳或是对方服务器性能不高导致请求失败时使用
流式文件下载
- 在requests请求时带上
stream=True
,实现流式下载,在请求大文件时使用
并发问题
简单使用ThreadPoolExecutor即可解决。
from future import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=int) as pool: # 声明了一个线程池
pool.map(func, 可迭代数据结构如list)
需要考虑对临界区资源进行加锁,可以使用l=threading.lock()
来声明一个锁,l.acquire()
来加锁,l.release()
来解锁