在日常爬虫工作中,需要先进行账号登陆才能爬取的网站不少,很多时候,在没有登录的情况下,我们可以访问一部分页面或请求一些接口,因为毕竟网站本身需要做SEO,不会对所有页面都设置登录限制。但是,不登录直接爬取会有一些弊端,弊端主要有以下两点。
- 设置了登录限制的页面无法爬取。
2.一些页面和接口虽然可以直接请求,但是请求一旦频繁,访问就容易被限制或者IP直接被封,,登陆后就好爬取了。
所以这种情况下我们爬虫程序就需要要搭建cookies池,与IP代理池不同,Cookies池具有针对性,如果你爬微博就要构建一个微博cookies池,爬知乎就需要构建一个知乎cookies池;而IP代理池是通用的,可供不同的爬虫任务共同使用。
本文我们以知乎来实现一个Cookies池的搭建过程。Cookies池中保存了许多知乎账号和登录后的Cookies信息,并且Cookies池还需要定时检测每个Cookies的有效性,如果某Cookies无效,那就删除该Cookies并模拟登录生成新的Cookies。同时Cookies池还需要一个非常重要的接口,即获取随机Cookies的接口,Cookies运行后,我们只需请求该接口,即可随机获得一个Cookies并用其爬取。cookie池的实现如下:
代码语言:javascript复制# Redis数据库地址、端口、密码
REDIS_HOST = "localhost" # 注意本地就写字符串形式的"localhost"
REDIS_PORT = 6379
REDIS_PASSWORD = None # 密码没有的话,就写None
# 产生器使用的浏览器
BROSER_TYPE = "chrome" # 注意浏览器类型,是字符串形式的
# 产生器类,如扩展其他站点,请在此配置
GENERATOR_MAP = { # 注意字典后的类名也是字符串形式的
"https://www.zhihu.com/follow",
"zhihu":"ZhihuCookiesGenerator"
}
# 测试类,如扩展其他站点,请在此配置
TESTER_MAP ={
"weibo": "zhihuValidTester",
"zhihu": "zhihuValidTester"
# 'XXX':'XXXCookiesGenerator'
}
TESTER_URL_MAP = {
'weibo': 'www.zhihu.com/follow',
'zhihu': 'www.zhihu.com/follow'
}
# 产生器和验证器循环周期
CYCLE = 120
# API地址和端口
API_HOST = '127.0.0.1' # host是字符串
API_PORT = 5000 # port不是字符串
# 产生器开关,模拟登录添加Cookies
GENERATOR_PROCESS = True
# 验证器开关,循环检测数据库中Cookies是否可用,不可用删除
TESTER_PROCESS = True
# API接口服务
API_PROCESS = True
代理池的使用是做爬虫的基础技术,现在的爬虫代理有api提取和隧道转发2种方式,这里给大家分享下隧道转发的,供大家参考,代码示例由亿牛云爬虫代理专业提供:
代码语言:javascript复制 #! -*- encoding:utf-8 -*-
import requests
import random
# 要访问的目标页面
targetUrl = "www.zhihu.com/follow"
# 要访问的目标HTTPS页面
# targetUrl = "www.zhihu.com/follow"
# 代理服务器(产品官网 www.16yun.cn)
proxyHost = "t.16yun.cn"
proxyPort = "31111"
# 代理验证信息
proxyUser = "ERWERE"
proxyPass = "897857"
proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {
"host" : proxyHost,
"port" : proxyPort,
"user" : proxyUser,
"pass" : proxyPass,
}
# 设置 http和https访问都是用HTTP代理
proxies = {
"http" : proxyMeta,
"https" : proxyMeta,
}
# 设置IP切换头
tunnel = random.randint(1,10000)
headers = {"Proxy-Tunnel": str(tunnel)}
resp = requests.get(targetUrl, proxies=proxies, headers=headers)
print resp.status_code
print resp.text