爬虫辅助相关
一、代理池
1 代理池的概念
去免费代理网站爬代理数据(ip、端口、代理类型(免费)),放到数据库
用python的web框架搭建一个代理池服务,建一个接口,每次朝服务端发请求,随机从数据库拿出一条代理
代理池服务跟主爬虫程序不相关,是一个独立的服务
2 问题
构建一个代理IP池,可能有下面这些问题:
* 代理IP从何而来?
许多刚接触爬虫的,都试过去西刺、快代理之类有免费代理的网站去抓些免费代理,还是有一些代理能用。当然,如果你有更好的代理接口也可以自己接入。
免费代理的采集也很简单,无非就是:`访问页面`` —> `正则/xpath提取` —> `保存`
* 如何保证代理质量?
可以肯定免费的代理IP大部分都是不能用的,不然别人还提供付费接口干嘛(不过事实上很多代理商的付费IP也不稳定,也有很多是不能用)。
所以采集回来的代理IP不能直接使用,检测的办法也很简单:可以写个程序不断的用代理访问一个稳定的网站,看是否可以正常访问即可。
这个过程可以使用多线/进程或异步的方式,因为检测代理是个很慢的过程。
* 采集回来的代理如何存储?
这里不得不推荐一个国人开发的高性能支持多种数据结构的NoSQL数据库[SSDB](http://ssdb.io/docs/zh_cn/),用于替代Redis。
支持队列、hash、set、k-v对,支持T级别数据。是做分布式爬虫很好中间存储工具。
* 如何让爬虫更方便的用到这些代理?
答案肯定是做成服务咯,Python有这么多的web框架,随便拿一个来写个api供爬虫调用。这样代理和爬虫架构分离有很多好处,
比如:当爬虫完全不用考虑如何校验代理,如何保证拿到的代理可用,这些都由代理池来完成。这样只需要安静的码爬虫代码就行啦。
3 代理池设计
代理池由四部分组成:
* ProxyGetter:
代理获取接口,找几个免费代理源,每调用一次就会抓取几个网站的最新代理放入DB,支持自定义扩展额外的代理获取接口;
* DB:
用于存放代理IP,SSDB或Redis(推荐SSDB)。
[安装参考](https://github.com/jhao104/memory-notes/blob/master/SSDB/SSDB%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE%E8%AE%B0%E5%BD%95.md)
* Schedule:
计划任务,用的APScheduler模块,定时去检测DB中的代理可用性,删除不可用的代理。同时也会主动通过ProxyGetter去获取最新代理放入DB;
* ProxyApi:
代理池的外部接口,由django或flask实现,功能是给爬虫提供与代理池交互的接口;
4 第三方代理池
爬虫代理IP池项目,主要功能为定时采集网上发布的免费代理验证入库,定时验证入库的代理保证代理的可用性,提供API和CLI两种使用方式。
同时你也可以扩展代理源以增加代理池IP的质量和数量。
下载代码
git clone git@github.com:jhao104/proxy_pool.git
或者 https://github.com/jhao104/proxy_pool/releases 下载zip文件
安装依赖
pip install -r requirements.txt
更新配置
# setting.py 为项目配置文件
# 配置API服务
HOST = "0.0.0.0" # IP
PORT = 5000 # 监听端口
# 配置数据库
DB_CONN = 'redis://:pwd@127.0.0.1:6379/0'
# 配置 ProxyFetcher
PROXY_FETCHER = [
"freeProxy01", # 这里是启用的代理抓取方法名,所有fetch方法位于fetcher/proxyFetcher.py
"freeProxy02",
# ....
]
# 如果已经具备运行条件, 可用通过proxyPool.py启动。
# 程序分为: schedule 调度程序 和 server Api服务
# 启动调度程序(开始到各个免费代理网站爬取代理数据,会先进行验证,有用的筛选出来)
python proxyPool.py schedule
# 启动webApi服务
python proxyPool.py server
# 朝服务端口发get请求,随机获取一个代理,用json()解析出来
requests.get("http://127.0.0.1:5000/get/").json()
# 删除一个代理
requests.get("http://127.0.0.1:5000/delete/?proxy={}".format(proxy))
源码 https://github.com/jhao104/proxy_pool#readme
4 自己建代理池服务
二、cookie池
cookie池搭建流程:
1、selenium写一套模拟登录脚本(需要一堆小号),跑起脚本,自动登录(验证码简单的),手动参与(验证复杂的)
2、拿到cookie,放到redis中
3、python的web框架搭建一个服务,写个接口:127.0.0.0:6000/get/,随机返回一个cookie
4、拿到cookie后,requests可以带着cookie发送请求爬数据,如果cookie失效从redis中剔除
三、破解验证码
1 验证码破解
方案一:
用代码去破解,需要会图像识别和处理,像12306这种用图像处理不了;
简单的数字加字母这种可以用代码破解,python有图像处理库,但复杂度高,一般不用来做破解;
不要浪费时间用代码破解,可以手动登录获取cookie,要么用打码平台
方案二:
专业打码平台,破解验证码(收费),它的图像识别也不是代码实现,而是人在后面点
# 申请超级鹰,注册
# 登录,下载sdk(代码如下),填入用户名密码,软件id
# 注意:很多网站的验证码改成了滑动认证,就很难破解了
# 不用自动登录,自己手动登录进去,拿到cookie,放到redis中,搭个cookie池,每次登录随机拿一个cookie去用
超级鹰sdk
import requests
from hashlib import md5
class Chaojiying_Client():
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: # 图片字节
codetype: # 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
if __name__ == '__main__':
# 实例化传入三个参数,超级鹰用户名、密码、软件ID
# 用户中心>>软件ID 生成一个
chaojiying = Chaojiying_Client('306334678', 'lqz12345', '903641')
# 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
# 需要从登录的网站扣取验证码图片,发给超级鹰识别
im = open('a.jpg', 'rb').read()
# 1902 验证码类型 官方网站>>价格体系
print(chaojiying.PostPic(im, 1902))
四、抓包工具
一般爬取web端数据,就用浏览器调试模式,也可以用抓包工具;爬取移动端数据,需要用抓包工具,抓包工具还用于移动端的测试
抓移动端的包,前提是手机和电脑主机要同一个网络。给手机配置代理,代理服务器主机名设为 PC 的 IP ,代理服务器端口设为 Fiddler上配置的端口 8888
手机通过代理发出的http请求的包都会经过电脑主机,配上抓包工具就能抓取,app也是http请求,但大多数返回的数据都加密
常用抓包工具
mac上一般用charles
windows上一般用fiddler
[fiddler配置和教程](https://www.cnblogs.com/woaixuexi9999/p/9247705.html)
js逆向和安卓逆向
1、web端反爬措施,用js生成加密串(比如把post请求提交的data生成加密串),抓包后需要逆向破解-->爬取js,但现在很多js混淆、js压缩,要逆向js比较难
2、因为手机和web是共用的接口,加密方法web有一套,移动端也有一套,破解移动端的加密比网站简单一点
使用安卓“改之理”打开app,里面是用jave写的代码,定位到加密方法-->扣出加密方法,用python重写加密方法生成加密串
python调用js函数
PyExecJS模块,依赖Node-js环境运行
一、简单使用
# js文件:my_js.js
function sum(a,b) {
return a + b
}
# python文件执行js代码
with open('my_js.js', 'rt', encoding='utf-8') as f:
etx = execjs.compile(f.read()) # 拿到js函数
ret = etx.call('sum', 4, 5) # 传入函数名, 参数--->执行js函数
print(ret) ===> 9
二、如果js代码是从浏览器扣出来的,直接执行js代码会报错,因为浏览器环境会有document、window对象,Node-js运行环境只有引擎
# 1 需要一个依赖Node-js的库来模拟浏览器环境:注意,是Node-js环境下载,不是python环境,npm install jsdom
# 2 在js文件中,在拷贝过来的js函数代码上方要加上以下一段代码:
```
const jsdom = require('jsdom');
const {JSDOM} = 'jsdom';
const dom = new JSDOM('<!DOCTYPE html><p>Hello world</p>');
window = dom.window;
document = window.document;
XMLHttpRequest; = window.XMLHttpRequest;
atob = window.atob;
```
# 3 安装完jsdom,会有一个node_modules, cwd指定该环境
with open('my_js.js', 'rt', encoding='utf-8') as f:
etx = execjs.compile(f.read(), cwd='node_modules')
ret = etx.call('sum', 4, 5)