前言
weixin.sogou.com
是一个反爬极其严厉的站点。
想要通过搜狗提供的 API 爬取微信公众号,你必须对以下几点印象深刻:
weixin.sogou.com
的 URL 构造,这是爬虫工程师的基本功。- 在不登录的情况下只能浏览前十页。
- 在登录的情况下只能爬取前一百页。
- 搜狗微信 的反爬措施是封 IP 和封 Cookie。
- 如果每五秒翻一页,大概翻二十页你会触发反爬:
我们今天不通过破解验证码的方式来突破反爬虫,在封 IP 和封 Cookie 两项措施中,最为严重的就是封 Cookie。如上图,其实并不是你的 IP 被封禁,而是你的 Cookie 被封禁。
事实上,对于一百页的爬取页面,一个健康的 IP 足矣。
以下,我们将从破解封禁 Cookie 破解封禁 IP 和展开讨论。
破解封禁Cookie
想要了解如何破解封禁 Cookie,我们必须先对互联网的 Cookie 和 Session 工作机制进行了解。
我们访问一个网站,过程大概分为四步。
第一步是我们的客户端向网站的服务器端发送一个 HTTP 请求,第二步服务器端发送一个 HTTP 响应到客户端,其中包含 Set-Cookie 头部。第三步客户端发送一个 HTTP 请求到服务器端,其中包含 Cookie 头部。第四步服务器端返回一个 HTTP 响应到客户端。
如图所示:
我为什么大费周章的去聊 Cookie 和 Session 呢?
要知道爬取 sogou.weixin.com
的 HTTP 请求的 Cookie 中,必须包含四个参数:SNUID
、SUID
、ppinf
和ppmdig
。
其中 SNUID
和 SUID
是访问 sogou.weixin.com
必须的,
而 ppinf
和 ppmdig
是访问后十页必须的。
对于禁封 Cookie,主要是禁封参数 SNUID
。假如你解除了下图的验证码封禁,其实只是给你传送了一个新的参数 SNUID
。
那么解决 Cookie 的封禁问题的答案就随之而来啦,只要我们构造一个 SNUID
参数池,我们姑且叫构造一个 Cookie 池吧。当我们的请求返回的状态码是 302
时,我们就使用一个全新的请求头,这时我们就可以成功突破 Cookie 的封禁。
那么我们如何构造这样一个 Cookie 池呢?
我们先在浏览器设置里清除客户端缓存的 Cookie:
再访问 sogou.weixin.com
:
在这个链接的响应头里我们清晰的看到了带有 SNUID
参数的 Set-Cookie
。
我们只要不断调用代理去访问:
https://weixin.sogou.com/weixin?type=2&query=宝多六花&ie=utf8&s_from=input&sug=n&sug_type=&w=01019900&sut=205&sst0=1543168556321&lkt=1%2C1543168556219%2C1543168556219
在响应头中就能提取出源源不断的 SNUID
参数。
破解封禁IP
当你的 IP 被封禁的时候,服务器可能给你返回的是 ”10054“,又或者“服务器积极地拒绝你的请求”。
而且,短时间内,你可能无法访问目标网站,这可是非常严肃的事情。
如何防止这种情况发生呢?
在碰到使用 IP 的情况时,我非常推荐开启 Shadowsocks 或者 v2rayN 的全局代理模式,使用虚拟 IP 可以有效防止我们的本源 IP 被封禁。
还有就是构造我们的代理池,使用代理进行爬取。
代理清洗
我上一篇文章写了构建代理池,免费的代理的使用率极低,我们非常有必要进行代理清洗。
首先把我们已经爬好的代理删除,不用害怕,我们的代理池足够强壮,几小时代理数量又能回到一千。
再找到 setting.py
文件,把里面的参数 TEST_URL
改成 “https://weixin.sogou.com”。
构建Cookie池
我们首先想到用 Redis 数据库来保存我们爬取的 SNUID
参数。
那么我们先编写一个 db.py
,保存和 Redis 数据库相关的函数。
db.py
import redis
# Redis数据库地址
REDIS_HOST = 'localhost'
# Redis端口
REDIS_PORT = 6379
# Redis密码,如无填None
REDIS_PASSWORD = None
REDIS_KEY = 'SougouWeixin'
class RedisClient(object):
def __init__(self, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD):
"""
初始化
:param host: Redis 地址
:param port: Redis 端口
:param password: Redis密码