1.支持设置HTTP Request Headers ,能设置UA。
2.支持代理服务器的设置。
3.它支持timeout超时机制。
4.它支持网页 的编码指定。
5.它支持服务器返回的错误处理 如果>400 and <500 直接记录日志,
如果错误码是500-600 则重新发起请求。
# -*- coding: utf-8 -*-
"""
Created on Tue Sep 17 19:46:32 2019
@author: Administrator
"""
import logging
from logging import handlers
import random
from urllib import request
from urllib import error
import time
import socket
# 日志
class Logger(object):
level_relations = {
'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'crit': logging.CRITICAL
} # 日志级别关系映射
#='info'
def __init__(self, filename, level, when='D', backCount=3,
fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
pass
# 创建日志的方法
def create_log(self,filename):
self.logger = logging.getLogger(filename)
return self.logger
def set_log_format(self, fmt):
format_str = logging.Formatter(fmt) # 设置日志格式
return format_str
def write_log(self, filename,level, when, backCount, fmt, encoding='utf-8'):
self.logger = Logger.create_log(self,filename)
self.logger.setLevel(self.level_relations.get(level)) # 设置日志级别
sh = logging.StreamHandler() # 往屏幕上输出
sh.setFormatter(Logger.set_log_format(self, fmt)) # 设置屏幕上显示的格式
# 实例化TimedRotatingFileHandler
# interval是时间间隔,backCount是备份文件的个数,如果超过这个个数,就会自动删除,when是间隔的时间单位,单位有以下几种:
# S 秒
# M 分
# H 小时、
# D 天、
# W 每星期(interval==0时代表星期一)
# midnight 每天凌晨
th = handlers.TimedRotatingFileHandler(filename=filename, when=when, backupCount=backCount,
encoding='utf-8') # 往文件里写入#指定间隔时间自动生成文件的处理器
th.setFormatter(Logger.set_log_format(self, fmt))
# 设置文件里写入的格式
self.logger.addHandler(sh) # 把对象加到logger里
self.logger.addHandler(th)
return sh,th,self.logger
def remove_hanler(self,filename, level, when, backCount, fmt, encoding='utf-8'):
sh,th,self.logger=Logger.write_log(self, filename, level, when, backCount, fmt, encoding='utf-8')
self.logger.removeHandler(sh)
self.logger.removeHandler(th)
#
# if __name__ == '__main__':
# filename="i://all.log"
# level='debug'
# when='D'
# backCount=3
# fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
#
# log = Logger(filename,level='debug')
# log.create_log(filename)
# log.write_log(filename, level, when, backCount, fmt, encoding='utf-8')
# log.logger.debug('debug')
# log.logger.info('info')
# log.logger.warning('警告')
# log.logger.error('报错')
# log.logger.critical('严重')
# # Logger('i://error.log', level='error').logger.error('error')
# log.remove_hanler( filename, 'error', 'D', 3, '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s', encoding='utf-8')
#
minRangeForProxy=1
maxRangeForProxy=10
minsleepTime=1
maxsleepTime=3
filename='i://all.log'
level = 'debug'
when = 'D'
backCount = 3
fmt = '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
log = Logger(filename, level='debug')
def downloadHtml(log,url,headers=[], useProxyRate=0,\
proxy={},timeout=socket._GLOBAL_DEFAULT_TIMEOUT,\
decodeInfo='utf-8',num_retries=5):
"""
这是一个爬取网页数据的函数
headers 它支持设置HTTP Request Headers ,能设置UA
proxy 支持代理服务器的设置
timeout 它支持timeout超时机制
decodeInfo 它支持网页 的编码指定
它支持服务器返回的错误处理 如果>400 and <500 直接记录日志
如果500-600 重新发起请求
"""
if random.randint(minRangeForProxy,maxRangeForProxy
) >useProxyRate:
proxy=None #不使用代理服务器
#创建proxy Handler
proxy_handler=request.ProxyHandler(proxy)
#创建opener
opener=request.build_opener(proxy_handler)
#设置http request 的headers
opener.addheaders=headers
#把proxy handler安装到urllib库中去
request.install_opener(opener)
#初始值将html的返回值设置成None
#如果成功的返回,则得到想要的html信息
#否则,None值不会发生改变
html=None
#发起请求
try:
#在这里考虑超时的问题urlopen有内部的timeout参数
res=request.urlopen(url,timeout=timeout)
html=res.read().decode(decodeInfo)
except UnicodeDecodeError:
log.logger.error("UnicodeDecodeError")
except error.URLError or error.HTTPError as e:
log.logger.error("Download Error")
#4xx,5xx
#出现4xx错误怎么办,直接记录日志
if hasattr(e,'code') and 400<=e.code <500:
log.create_log(filename)
log.write_log(filename, level, when, backCount, fmt, encoding='utf-8')
log.logger.debug('debug')
log.logger.info('info')
log.logger.warning('警告')
log.logger.error('报错')
log.logger.critical('严重')
return html
#如果出现5xx错误怎么办,服务器的问题
if num_retries>0:
#如果状态码为500-600之间,则继续抓取,直到抓取的次数
#超出最大上限
if hasattr(e,"code") and 500 <=e.code<600:
#如果请求返回服务器失败随机休息1到3秒钟,然后继续获取当前.
time.sleep(random.randint(minsleepTime,maxsleepTime))
html=downloadHtml(url,
headers,proxy,useProxyRate,
timeout,num_retries-1)
return html
headers=[("User-Agent", "Mozilla/5.0 (Windows NT 6.1;\
Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)\
Chrome/76.0.3809.132 Safari/537.36")]
url="http://www.baidu.com"
#http://121.199.42.16/VAD/GetIp.aspx?act=get&num=200&time=60&plat=1&re=0&type=0&ow=1&prov=浙江省
proxy_addr={"http","ip:端口号"}
print(downloadHtml(log,url=url,
headers=headers,proxy=proxy_addr))
log.remove_hanler( filename, 'error', 'D', 3, '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s', encoding='utf-8')
返回百度首页。
H:\ANACONDA\python.exe I:/ainlp/spiderBasic.py
百度一下,你就知道