前言

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 中,必须包含四个参数:SNUIDSUIDppinfppmdig

其中 SNUIDSUID 是访问 sogou.weixin.com 必须的,

ppinfppmdig 是访问后十页必须的。

对于禁封 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 = NoneREDIS_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密码"""self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True)def push(self, snuid):"""从列表头部插入snuid,:param snuid: 参数 snuid:return: 添加结果"""self.db.lpush(REDIS_KEY, snuid)def pop(self):"""移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。:return: 尾部的snuid"""return self.db.brpop(REDIS_KEY)def count(self):"""获取数量:return: 数量"""return self.db.llen(REDIS_KEY)

我们以前讲到了 Redis 数据库支持的数据类型有字符串,散列,列表,集合,这里我们选用的数据类型是列表。

为什么选用列表呢?

因为列表有序,我们用列表的 lpush() 函数,实现对列表左侧添加 SNUID ,用 brpop() 函数实现调用列表最右边的 SNUID

我们再在 db.py 中添加下列几项,可以方便我们提取代理。

from random import choice
from cookiespool.error import PoolEmptyErrorPROXY_REDIS_KEY = 'proxies'
#最大评分
MAX_SCORE = 100
MIN_SCORE = 0def random(self):"""随机获取有效代理,首先尝试获取最高分数代理,如果不存在,按照排名获取,否则异常:return: 随机代理"""result = self.db.zrangebyscore(PROXY_REDIS_KEY, MAX_SCORE, MAX_SCORE)if len(result):return choice(result)else:result = self.db.zrevrange(PROXY_REDIS_KEY, 0, 100)if len(result):return choice(result)else:raise PoolEmptyErrordef decrease(self, proxy):"""代理值减一分,小于最小值则删除:param proxy: 代理:return: 修改后的代理分数"""score = self.db.zscore(PROXY_REDIS_KEY, proxy)if score and score > MIN_SCORE:print('代理', proxy, '当前分数', score, '减1')return self.db.zincrby(PROXY_REDIS_KEY, proxy, -1)else:print('代理', proxy, '当前分数', score, '移除')return self.db.zrem(PROXY_REDIS_KEY, proxy)

紧接着我们编写一个名为 spider.py 的文件,里面装载爬取 SNUID 参数的代码。

值得注意的是,在爬取 SNUID 的过程中,我们只要寻找到一个可用的代理,然后使用该代理不停循环,不断从响应头里提取成百上千个 SNUID ,这部分的反爬并不严重。

而无效的代理,我们执行扣分程序,并且不想再看到它。

import re
import time
import requests
from cookiespool.db import RedisClient#爬取间隔
SLEEPTIME = 10headers = {'Host': 'weixin.sogou.com','User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2','Accept-Encoding': 'gzip, deflate, br','Referer': 'https://weixin.sogou.com/','Connection': 'keep-alive','Upgrade-Insecure-Requests': '1',
}
url = 'https://weixin.sogou.com/weixin?type=2&query=nba&s_from=input&_sug_=n&_sug_type_=&w=01019900&sut=5296&sst0=1543167134916&lkt=10%2C1543167129476%2C1543167134813'class Spider():def __init__(self):self.redis = RedisClient()def getHTML(self):proxy = self.redis.random()proxies = {'http': 'http://' + proxy,'https': 'https://' + proxy,}try:r = requests.get(url, allow_redirects=False, headers=headers, proxies=proxies, timeout=30)print('正在使用:', proxy)if r.status_code == 200:header = r.headersprint(header)snuid = re.findall('(SNUID=.*?;)', header['Set-Cookie'])print(snuid)if len(snuid) != 0:self.redis.push(snuid[0])print('Redis插入:', snuid[0])while snuid != None:self.circle(proxy)time.sleep(SLEEPTIME)else :self.redis.decrease(proxy)else:self.redis.decrease(proxy)except TimeoutError:passdef circle(self, proxy):proxies = {'http': 'http://' + proxy,'https': 'https://' + proxy,}try:r = requests.get(url, allow_redirects=False, headers=headers, proxies=proxies)print('循环代理:', proxy)if r.status_code == 200:header = r.headersprint(header)snuid = re.findall('(SNUID=.*?;)', header['Set-Cookie'])if len(snuid) != 0:self.redis.push(snuid[0])print('Redis插入:', snuid[0])return snuidelse:snuid = Nonereturn snuidexcept:snuid = Nonereturn snuid

最后我还编写了可有可无的 api.py ,它可以提供调用 SNUID 的接口,这里不费笔墨。

代码同步在 GitHub 上,成功构建代理池后,我们将在下节正式爬取 sogou.weixin.com

最后

欢迎关注我的公众号 爬虫小栈。

搜狗微信文章爬取(上)相关推荐

  1. 搜狗微信文章爬取(中)

    GitHub: https://github.com/utopianist/SougouWeixin 前言 上节,我们已经成功构造了包含参数 SNUID 的 Cookie 池,这节我们将正式爬取 we ...

  2. 爬取搜狗微信文章笔记1

    爬取搜狗微信文章笔记1 错误1 ```pythonprint('https://weixin.sogou.com'+index) TypeError: can only concatenate str ...

  3. python3实现微信公众号文章爬取

    基于搜狗微信的文章爬取 前言:文章仅用于学习交流,不足之处欢迎小伙伴指正! 一.功能介绍: 已实现功能: 1.爬取搜狗微信上的分类一栏的所有事件及其他的所有标题事件和加载更多,返回文章链接与标题,并存 ...

  4. python微信爬取教程_[python]微信公众号文章爬取

    [python]微信公众号文章爬取 需求 爬取一些微信公众号的文章 数据来源 1.搜狗微信搜索,可以搜索微信公众号文章,但只能显示该公众号最近十篇的文章 2.通过个人微信公众号中的素材管理,查看其他微 ...

  5. 微信公众号文章爬取方法整理

    微信公众号文章爬取方法整理 1.用python爬取 http://blog.csdn.net/d1240673769/article/details/75907152 实现方法:通过微信提供的公众号文 ...

  6. Python 微信公众号的文章爬取

    Python 微信公众号文章爬取 一.思路 二.接口分析 三.实现 第一步: 第二步: 1.请求获取对应公众号接口,取到我们需要的fakeid 2.请求获取微信公众号文章接口,取到我们需要的文章数据 ...

  7. 搜狗·疫情数据爬取(Python)

    上周已经分享过搜狗·疫情数据爬取(R语言),这次分享一下搜狗·疫情数据爬取(Python) 不说废话,直接上代码.有什么问题,可以在留言区讨论. from urllib import request ...

  8. 【java】微信文章抓取

    1.搜狗微信url解析 以搜索湖北师范大学为例: 请求的url为: http://weixin.sogou.com/weixin?query=%E6%B9%96%E5%8C%97%E5%B8%88%E ...

  9. 知乎登录js逆向及文章爬取js逆向

    知乎登录js逆向及文章爬取js逆向 **在此声明:**本文章仅仅用于学习交流,不得用于商业活动. 登录支持账号密码登录及知乎移动端软件扫码登录. 文章爬取是把原文章的原样近似爬取,包括图片,链接,及评 ...

  10. 微信文章抓取:微信临时链接转永久链接方法,一招摆脱链接过期烦恼

    上一篇文章<微信文章抓取:微信公众号文章抓取常识之临时链接.永久链接>中介绍了微信临时链接和微信永久链接的情况.那么大家一定会有一个问题:如何让临时链接不再过期?或者说如何把临时链接转换为 ...

最新文章

  1. Win7 64位的SSDTHOOK(1)---SSDT表的寻找
  2. pps服务器未响应_服务响应时间与分布
  3. Factory Method模式
  4. Linux mount: Structure needs cleaning 错误解决方法
  5. 物权法全文内容有哪些呢-广告外链_SEO优化的站外优化工作有哪些?
  6. Centos7安装32位库用来安装32位软件程序
  7. 悄悄告诉你如何快速突破大厂逻辑题
  8. 【Ubuntu和本地电脑互传文件】
  9. 数据结构与算法分析(一)基础
  10. 好玩的Deep Dream模型
  11. 身份证验证接口有哪些验证类型
  12. java 给pdf文档加水印
  13. git 将暂存区文件提交_git文件状态,暂存与提交
  14. 如何在matlab中表达点集,matlab练习程序(点集配准的SVD法)
  15. 什么是深度学习、强化学习
  16. 2021鹏业安装算量软件常见问题整理(二十)
  17. 使用联邦学习解决推荐系统中的隐私泄露问题
  18. Mac安装brew(2020年踩过无数坑后亲测有效的方法)
  19. 线性代数:置换、转置矩阵和向量空间
  20. Spline(三次样条插值)

热门文章

  1. 轻量级神经网络——shuffleNet
  2. 天然气流量计选型指南
  3. 微型计算机原理8255跑马灯,单片机+74LS138译码器+跑马灯+8255A+8253方波实验详解
  4. 苹果android投屏,iphone怎么投屏到mac?苹果手机投屏到苹果电脑方法
  5. 2.3 sklearn中的metrics.roc_curve评价指标
  6. itchat微信多开
  7. Java基础--文件合并器
  8. 概率论基础知识整理(一)
  9. 英文简历模板计算机专业,计算机专业毕业生英文简历模板
  10. 下载安装配置Pycharm免费版