爬蟲常用程式碼--基礎爬蟲(含代理和日誌)
阿新 • • 發佈:2018-12-16
import logging
import sys
import urllib.request
import random
import ssl
# 全域性取消安全證書驗證,如果沒有這一句會報錯
ssl._create_default_https_context = ssl._create_unverified_context
# 建立日誌基本上就是這個套路
# 建立例項,引數為日誌檔名
logger = logging.getLogger("basicspider")
# 定義日誌的格式,引數分別為:時間,異常登記
formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s" )
# 開始建立日誌:檔案日誌,終端日誌
# 建立檔案日誌
file_handler = logging.FileHandler("basicspider.log")
# 設定檔案日誌格式
file_handler.setFormatter(formatter)
# 建立終端日誌
consle_handler = logging.StreamHandler(sys.stdout)
consle_handler.setFormatter(formatter)
# 設定日誌預設級別,比這個級別高的錯誤都會寫進來。10是debug,20是INFO,30是WARNING,40是ERROR,50是FATAL
# 一般來說,除錯的時候設定為debug,但是釋出的時候最好設定到error,否則會顯得很外行
logger.setLevel(logging.INFO)
# 把檔案日誌和終端日誌新增到日誌處理器中
logger.addHandler(file_handler)
logger.addHandler(consle_handler)
# 以上建立日誌過程結束
PROXY_RANGE_MIN = 1
PROXY_RANGE_MAX = 10
PROXY_RANGE_NUM = 11
NUMRETRIES = 10
TIMEOUT = 10
def downloadHtml(url, headers= [], proxy={}, num_retries=10, timeout=10, decodeInfo="utf-8"):
"""爬蟲的get請求,考慮了UA等http request head部分的設定
支援代理伺服器處理
如果返回的狀態碼不是200的處理方式
考慮了超時問題和網頁編碼格式
"""
#logger.debug("download start")
# 一般來說使用UA池和代理伺服器池訪問頁面會不容易被反爬
# 動態的調整代理伺服器的使用策略
html = None # z最終返回值是一個html,在這裡設定一個初始值,這樣一定可以返回
if num_retries <= 0:
return html
if random.randint(PROXY_RANGE_MIN, PROXY_RANGE_MAX) >= PROXY_RANGE_NUM: # 70%概率不使用代理伺服器
logger.info("No Proxy")
proxy = None
else:
logger.info("Already Use Proxy")
proxy_handler = urllib.request.ProxyHandler(proxy)
#logger.debug("download completed")
opener = urllib.request.build_opener(proxy_handler)
opener.addheaders = headers
urllib.request.install_opener(opener)
try:
response = urllib.request.urlopen(url)
html = response.read().decode(decodeInfo)
except UnicodeDecodeError as u:
logger.error("UnicodeDecodeError:", u)
except urllib.error.URLError or urllib.error.HTTPError as e:
logger.error("urllib error:", e)
if hasattr(e, "code") and 400 <= e.code < 500:
logger.error("Client Error")
elif hasattr(e, "code") and 500 <= e.code < 600:
html = downloadHtml(url, headers, proxy, timeout,
decodeInfo, num_retries-1)
logger.error("Server Error")
except:
logger.error("Download Error")
return html
if __name__ == '__main__':
url = "http://www.baidu.com"
headers = [("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36")]
proxy = {"http": "106.75.164.15:3128"}
print(downloadHtml(url, headers, proxy, NUMRETRIES, TIMEOUT))
# 注意 日誌remove必須在外邊,保證可以remove
logger.removeHandler(file_handler)
logger.removeHandler(consle_handler)