文章目录
- 一、使用tesseract做OCR验证码识别
- 二、代理服务器设置
- 三、反爬与防反爬
- 四、封装一个抓取页面的函数
一、使用tesseract做OCR验证码识别
1、cookie, session的作用
用户曾经访问过个这个网站,我们需要在HTTP协议之外用一些额外的信息和技术来标识这个用户曾经来过为了让用户体验更好;所以我们的爬虫程序可以巧妙的利用这个漏洞来达到登录获取信息的效果。
2、安装tesseract
pip install pytesseract
3、测试tesseract
1)from pytesseract import *
2)然后,在captchaTest. py程序中有一张验证码的图片
3)去噪音,找出验证码的色彩;
4)背景色与前景色的区分;
5)提取出一个个字符;
6)使用余弦相似度来计算两个字符之间的相似,
https: L /blog. csdn. net /whi terbear/article/details .
7)得到当前字符最大概率匹配的样本集中的字
4、注意
验证码这一关是涉及机器学习方面的内容,里面的水很深,因此处理验证码时一定要考虑好时间成本。如果图像识别技术实在搞不定验证码这一关,可以选择使用打码平台,最终都无法解决,那也只能手动输入了。
5、打码平台运作的方式
1)首先在打码平台注册账号,获取到合法的Key, ID等信息;
2)使用这些Key, ID去调对方的API:读取文件成字节流,做一次Base64转码,去调API接口,返回结果;
3))到结果,进行下一-步操作;如果出错,根据返回结果来判断如果排错。
二、代理服务器设置
1、代理服务器:借助别人的手来完成访问,将自己的ip地址给伪装起来,爬虫时不会被服务器发现恶意访问
2、设置代理服务器IP:打开控制面板的Internet选项,点连接,设置,代理服务器,输入对应的地址和端口号(port)
3、IP和MAC地址的区别
HTTP数据包在传递过程,源地址和目标地址是不变的。填写的是IP地址,发包过程中经历各个路由器使用的是MAC地址,不同的路由器就有不同的物理地址,即MAC地址,因此这个MAC地址是不断变化的。
4、代理服务器使用方法
import urllib.request
def use_http_proxy(proxy_addr, url):
proxyH = urllib.request.ProxyHandler({"https":proxy_addr})
opener = urllib.request.build_opener(proxyH,
urllib.request.HTTPHandler)
urllib.request.install_opener(opener)
res = urllib.request.urlopen(url,timeout=6)
data = res.read().decode("utf-8")
return data
if __name__ == "__main__":
proxy_addr = "114.224.223.164:9999"
data = use_http_proxy(proxy_addr, "https://www.sina.com.cn/")
print(data)
三、反爬与防反爬
1、网站如何发现爬虫
- 单一IP非常规的访问频次;
- 单一IP非常规的数据流量;
- 大量重复简单的网站浏览行为,只下载网页,没有后续的JS,CSS请求;
- 通过一些陷阱来发现爬虫,例如一些通过CSS对用户隐藏的链接,只有爬虫才会访问。
2、网站一般如何进行反爬虫
- 大量使用动态网页,是的爬虫的爬取难度增加,重要数据都拿不到,即使爬虫用了Web环境来渲染(内置浏览器),也会大大增加爬虫的负担和爬虫时间; (当采用动态加载的技术,对服务器的负担也会大大减轻)。
- 基于流量的拒绝,开启带宽限制模块,限制每个IP最多连接数,最大带宽等。
3、如何发现自己被反爬了
- 频繁验证码的出现
- Unusual content delivery delay非常规的延时;。
- Freguent response with HTTP 403,404, 301 or 50x error
4、防反爬策略
1)User-Agent 池
2)代理服务器池
3)CookieJar 等的管理
4)协议的细节考虑,如:需要大量的实践经验总结的。抓取数据时不处理CSS,JS等,nofollow属性,css 的display属性,探测陷阱
验证refer locator等。
5)使用分布式的多机策略,爬慢点,把爬虫放到访问频繁的主站IP子网下,比如教育网;
6)使用了规则来批量爬取,需对规则进行组合
7)验证码的处理:机器学习,图像识别
8)尽可能遵守Robots协议
四、封装一个抓取页面的函数
以下是完整代码,关于各个地方的详细说明都在注释中了。
import logging
import sys
import random
from urllib import request
from urllib import error
from urllib import parse
import time
logger = logging.getLogger("testLogger")
formatter = logging.Formatter('%(asctime)s \t %(levelname)s \t %(message)s')
file_handler = logging.FileHandler("testLogger2.log")
file_handler.setFormatter(formatter)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
logger.setLevel(logging.DEBUG)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
minRangeForProxy = 1
maxRangeForProxy = 10
minSleepTime = 1
maxSleepTime = 3
def downloadHtml(url, headers=[],
proxy={}, useProxyRate=0,
timeout=None, decodeInfo="utf-8",
num_retries=5):
"""
这是一个爬取网页数据的函数
:param url:网页地址
:param headers:请求头,包括User-Agent,Cookie,Host,Connection
:param proxy:代理服务器的社会中
:param timeout:超时设置,超过时间就报错
:param decodeInfo:网页编码的指定
:param num_retries:如果错误,重新尝试的次数
:return:服务器返回错误状态码的处理,如果是400+则直接记录日志,如果是500+则重新跑几次downloadHtml函数
"""
if random.randint(minRangeForProxy,
maxRangeForProxy) >= useProxyRate:
proxy = None
print("No using proxy!")
proxy_handler = request.ProxyHandler(proxy)
opener = request.build_opener(proxy_handler)
request.install_opener(opener)
opener.addheaders = headers
html = None
try:
res = request.urlopen(url)
html = res.read().decode(decodeInfo)
except UnicodeDecodeError:
logger.error("UnicodeDecodeError")
except error.URLError or error.HTTPError as e:
logger.error("Download Error")
logger.error("Client Error!")
return html
if num_retries > 0:
time.sleep(random.randint(minSleepTime, maxSleepTime))
if hasattr(e, 'code') and 500 <= e.code < 600:
html = downloadHtml(url, headers,
proxy, useProxyRate,
timeout, decodeInfo, num_retries-1)
return html
headers = [("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36",)]
proxy_addr = {"http": "114.224.223.164:9999"}
print(downloadHtml("http://www.baidu.com/",headers=headers,
proxy=proxy_addr))
logger.removeHandler(file_handler)
logger.removeHandler(console_handler)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)