urllib爬虫封装(可设置代理,记录日志)方法

urllib爬虫封装(具体其他功能根据需求完善)

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










    
    
    
	
    
    
    
    
	
	
	
	
	
	
	
	
	
	
    
    百度一下,你就知道
    









    




    



	
    
    

你可能感兴趣的:(爬虫)