# 获取证书到期时间

### 方法二

> pip install python-dateutil pytz requests

```python
#!/usr/bin/env python3  
  
import ssl, socket  
import requests  
from dateutil import parser  
import pytz  
from datetime import datetime, timezone

requests.packages.urllib3.disable_warnings()  
  
try:  
    _create_unverified_https_context = ssl._create_unverified_context  
except AttributeError:  
    # Legacy Python that doesn't verify HTTPS certificates by default  
    pass  
else:  
    # Handle target environment that doesn't support HTTPS verification  
    ssl._create_default_https_context = _create_unverified_https_context  
  
  
def get_domain_content(domain):  
    requests.packages.urllib3.disable_warnings()  
    url = 'https://' + domain  
    response = requests.get(url, verify=False).headers  
    print(response)  
  

def get_my_domain(mydomain):  
    try:  
        socket.setdefaulttimeout(5)  
        my_addr = socket.getaddrinfo(mydomain, None)  
        c = ssl.create_default_context()  
        s = c.wrap_socket(socket.socket(), server_hostname=mydomain)  
        s.connect((mydomain, 443))  
        my_cert = s.getpeercert()  
        get_my_cert_dated(mydomain, my_cert, my_addr)  
    except ssl.CertificateError and socket.gaierror as e:  
        pass  
  
  
def get_my_cert_dated(domain, certs, my_addr):  
    cert_beginning_time = parser.parse(certs['notBefore']).astimezone(pytz.utc)  
    cert_end_time = parser.parse(certs['notAfter']).astimezone(pytz.utc)  
  
    print('域名:(%s)  证书失效时间: %s' % (domain,  cert_end_time))  
    print('域名:(%s)  证书剩余天数: %s' % (domain,  (cert_end_time - datetime.now(timezone.utc)).days))  
  
  
def read_domain_files():  
    with open('./domain.txt', 'r',  
              encoding="utf-8") as file:  
        for domain in file:  
            try:  
                get_my_domain(domain.strip())  
            except Exception as e:  
                print('域名: (%s)-%s' %(domain.strip(), e))  
  
  
if __name__ == "__main__":  
    read_domain_files()  
```

准备domain.txt一个域名一行，可从DNS导出记录

```python
cat > domain.txt << EOF  
linuxeye.com  
www.linuxeye.com  
oneinstack.com  
www.linuxeye.com  
EOF  
```

执行：

```python
python3 domain-ssl-check.py  sEOF  
```

### 方法三

1、通过证书获取

```bash
openssl x509 -in <cert>.pem -noout -dates
```

2、通过域名获取

```bash
echo | openssl s_client -servername <doman> -connect <doman>:443 2>/dev/null | openssl x509 -noout -dates
```

3、通过脚本获取

```python
# coding: utf-8 
# 查询域名证书到期情况

import re
import subprocess
from datetime import datetime


def get_re_match_result(pattern, string):
    match = re.search(pattern, string)
    return match.group(1)


def parse_time(date_str):
    return datetime.strptime(date_str, "%b %d %H:%M:%S %Y GMT")


def format_time(date_time):
    return datetime.strftime(date_time, "%Y-%m-%d %H:%M:%S")


def get_cert_info(domain):
    """获取证书信息"""
    cmd = f"curl -Ivs https://{domain} --connect-timeout 10"

    exitcode, output = subprocess.getstatusoutput(cmd)

    # 正则匹配
    start_date = get_re_match_result('start date: (.*)', output)
    expire_date = get_re_match_result('expire date: (.*)', output)

    # 解析匹配结果
    start_date = parse_time(start_date)
    expire_date = parse_time(expire_date)

    return {
        'start_date': start_date,
        'expire_date': expire_date
    }


def get_cert_expire_date(domain):
    """获取证书剩余时间"""
    info = get_cert_info(domain)
    print(info)

    expire_date = info['expire_date']

    # 剩余天数
    return (expire_date - datetime.now()).days


if __name__ == "__main__":
    domain = 'www.baidu.com'
    expire_date = get_cert_expire_date(domain)
    print(expire_date)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://close.gitbook.io/yun-wei-bi-ji/python/python-xiao-ji-qiao/huo-qu-zheng-shu-dao-qi-shi-jian-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
