惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Heimdal Security Blog
A
Arctic Wolf
K
Kaspersky official blog
V
Vulnerabilities – Threatpost
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Simon Willison's Weblog
Simon Willison's Weblog
L
LINUX DO - 热门话题
MongoDB | Blog
MongoDB | Blog
T
Threat Research - Cisco Blogs
D
Docker
爱范儿
爱范儿
T
Tenable Blog
C
Check Point Blog
B
Blog
C
Cisco Blogs
Vercel News
Vercel News
The Cloudflare Blog
T
Threatpost
NISL@THU
NISL@THU
T
Tor Project blog
V2EX - 技术
V2EX - 技术
P
Palo Alto Networks Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tailwind CSS Blog
G
GRAHAM CLULEY
P
Privacy & Cybersecurity Law Blog
SecWiki News
SecWiki News
博客园 - 司徒正美
S
Security @ Cisco Blogs
GbyAI
GbyAI
S
Secure Thoughts
Microsoft Security Blog
Microsoft Security Blog
The Register - Security
The Register - Security
Recorded Future
Recorded Future
Cloudbric
Cloudbric
Webroot Blog
Webroot Blog
N
News and Events Feed by Topic
Y
Y Combinator Blog
博客园_首页
T
Troy Hunt's Blog
The Hacker News
The Hacker News
雷峰网
雷峰网
Google DeepMind News
Google DeepMind News
U
Unit 42
AWS News Blog
AWS News Blog
PCI Perspectives
PCI Perspectives
V
Visual Studio Blog
博客园 - 聂微东
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell

风萧古道 - 勤学苦练,年复一年

游戏服务器开发经验(五)应对复杂需求 沉浸式体验东汉末年生活 - 《真三国无双 起源》玩后感 怒其不争!致2025年HLTV的Top18-NiKo Linux家用服务器维护指南 游戏服务器开发经验(四)避免写Bug的习惯、技巧和心态 游戏服务器开发经验(三)线上维护 游戏服务器开发经验(二)避免内存泄露 游戏服务器开发经验(一)道具防刷 35岁找不到工作,绝对不会是软件开发人员的结局 用爱发电项目开发两个月的心得体会 以魏延“子午谷奇谋”讨论软件需求可行性问题 MQTT协议中可变长度的具体计算方式(有计算过程解析) 关于游戏服务器配置表功能的探讨 Java并发编程中上锁的几种方式 如何用C++分割一个字符串? CSAPP第二章-信息的表示与处理 我的自我介绍 Windows XP虚拟机中文版无需激活下载 Java TreeSet的一些用法和特性 Linux C++ Socket实战 传统软件服务器与游戏服务器架构区别 独立个人项目开发心得 - 任务切分、挑战性、实用性和半途而废 使用Python实现简单UDP Ping 使用Python开发一个简单的web服务器 Kotlin手动实现一个最简单的哈希表 Kotlin实现二叉堆、大顶堆、优先级队列 搭建Spark实战环境(3台linux虚拟机集群)(一)样板机的搭建 Springboot操作MongoDB,包括增改查及复杂操作 Unison在Linux下的安装与使用 Java实现类似WINSCP访问远程Linux服务器,执行命令、上传文件、下载文件 Python连接MongoDB和Oracle实战 MongoDB常用查询语句 vue和springboot项目部署到Linux服务器 Python的一些用法(可能不定时更新) java正则表达式 - 双反斜杠(\)和Pattern的matches()与find() 简述爬虫对两种网站的不同爬取方式 Vue的路由配置及手动改地址栏为啥又跳转回来?? [JavaScript]JS基础知识 [Mybatis]逆向工程中Select语句查询不出‘TEXT’字段 [编译原理]FIRST、FOLLOW和SELECT [Spring]Spring学习笔记 [算法]分布估计算法 - 一种求解多维背包问题的混合分布估计算法_王凌 [日常]我做独立博客的原因 人间值得 深入理解计算机系统 想想就开心! 最重要的事,只有一件 藏书 被讨厌的勇气 关于 简历 朋友 尊重自己:给予与接收的心灵艺术
一个被废弃的项目——自动爬取信息然后发给我自己邮箱上
JonathanLin · 2020-02-09 · via 风萧古道 - 勤学苦练,年复一年

这是一个python项目。

使用到的技术包括爬虫和发邮件

代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/2/5 22:49
# @Author  : Johnathan Lin
import time
import requests
import random
import json
import re
from bs4 import BeautifulSoup
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from urllib.parse import urljoin
from bs4.element import NavigableString

# 第三方 SMTP 服务
mail_host = "smtp.163.com"  # 设置服务器
mail_user = "你的邮箱"  # 用户名
mail_pass = "你的密码"  # 口令

# 发送人和接收人
sender = '你的邮箱' # 自己发给自己就可以了,
receivers = ['你的邮箱']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱

# 爬虫请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
}


def send_mail(date, msg):
    """
    发送邮件
    :param date: 日期
    :param msg: XX内容
    :return:
    """
    mail_msg = msg
    message = MIMEText(mail_msg, 'html', 'utf-8')
    message['From'] = Header("我的发件邮箱", 'utf-8')
    message['To'] = Header("我的收件邮箱", 'utf-8')

    subject = date + ' ' + 'XXXXXXX情况'
    message['Subject'] = Header(subject, 'utf-8')

    try:
        smtpObj = smtplib.SMTP()
        smtpObj.connect(mail_host, 25)  # 25 为 SMTP 端口号
        smtpObj.login(mail_user, mail_pass)
        smtpObj.sendmail(sender, receivers, message.as_string())
        print("邮件发送成功")
    except smtplib.SMTPException as e:
        print("Error: 无法发送邮件")
        print(repr(e))


def regular_res(res):
    """
    把不规则json转为规则json
    :param res: 请求得到的字符串
    :return: 合法的json字符串
    """
    res = re.sub(r'\n', '', res)
    res = re.sub(r'\t', '', res)
    res = re.sub(r'chnldesc', '\"chnldesc\"', res)
    res = re.sub(r'recordCount', '\"recordCount\"', res)
    res = re.sub(r'docs', '\"docs\"', res)
    res = re.sub(r'docid', '\"docid\"', res)
    res = re.sub(r'title', '\"title\"', res)
    res = re.sub(r'url', '\"url\"', res)
    res = re.sub(r'time ', '\"time\"', res)
    return res


def crawl_data(date):
    """
    爬取文档
    :param date: 日期,用于测量是否是当天的
    :return: 目标页面的url
    """
    url = 'http://xxxxxxxxxx?r=' + str(random.random())
    response = requests.get(url, headers=headers)
    res = str(response.content, encoding='utf-8')
    response.close()
    res = regular_res(res)
    json_obj = json.loads(res)
    for doc in json_obj['docs']:
        if doc['title'] == 'XXXXXXXX情情况' and doc['time'] == date:
            return doc['url']
    return ''


def timestamp_to_date(timestamp):
    """
    时间戳转时间年-月-日
    :param timestamp: 时间戳
    :return: 时间字符串
    """
    return time.strftime(time.strftime("%Y-%m-%d", time.localtime(timestamp)))


def crawl_content(res_url):
    response = requests.get(res_url, headers=headers)
    html = str(response.content, encoding='utf-8')
    response.close()
    html_content = BeautifulSoup(html, 'lxml')
    news_content = ''
    news_block = html_content.select('div.TRS_Editor')[0]
    [s.extract() for s in html_content.select('style')]
    [s.extract() for s in html_content.select('script')]
    for block in news_block.contents:
        if not isinstance(block, NavigableString):
            del block['style']
            del block['class']
            del block['align']
            # print(block.name)
            if block.name == 'a':
                block['href'] = urljoin(res_url, block['href'])
            if block.name == 'h2' or block.get_text().strip() == '':
                continue
        news_content += str(block).replace('\r', '').replace('\n', '').replace('\t', '').strip()
    return news_content


if __name__ == '__main__':
    # # 2.6的时间戳
    timestamp = 1580918400
    while (True):
        # 每隔60秒爬一次
        time.sleep(60)
        # 获取下次需要的日期
        date = timestamp_to_date(timestamp)
        # 请求得到目标url
        res_url = crawl_data(date)
        if res_url == '':
            continue
        # 找到相应的请求,爬取内容
        news_content = crawl_content(res_url)
        # 发送邮件
        send_mail(date, news_content)
        # 爬取下一天的内容
        timestamp += 86400
        # 2.9之后停止
        if timestamp == 1581264000:
            break

使用网易邮箱app,可以第一时间接到自己发的邮件。

这里测试过QQ邮箱,把我的邮件判定为垃圾邮件,直接被退回了。

测试结果: (我做完然后发现爬不动的时候,感觉到了自己在吃人血馒头,故将人名隐去)

在本地测试通过后,放到服务器上,使用

放在后台执行,本以为万事大吉,结果才爬了一小会人报了错。

ConnectionResetError: [Errno 104] Connection reset by peer

服务器把我的连接请求关闭了。

网上查找资料的结果是,爬取过频,对面关闭服务器我还继续请求。

但我一分钟请求一次,也不算特别快了。

我当然可以写个方法,在读取异常之后继续爬,如:

def request_while_response(url, type, headers, data, open_proxy, sleep_time):
    """
   发送请求,规避10054错误,直至请求成功
   :param url: 请求路径
   :param type:  请求类型(get或post)
   :param headers: 请求头
   :param data: 请求参数对象
   :param open_proxy:  是否使用代理
   :return:  请求得到的文本
   """
    r = ''
    while True:  # 循环
        try:
            # request()是发送请求的方法,我将requests包封装成了
            r = request(url, type, headers, data, open_proxy)
        except (requests.exceptions.SSLError, requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout) as e:
            if 'bad handshake' in str(e) or '10054' in str(e) or 'Read timed out' in str(e):  # 上述2种异常
                time.sleep(sleep_time)
                continue  # 继续发请求
            else:
                raise Exception(e)  # 其他异常,抛出来
        break  # 无异常就跳出循环
    return r  # 返回响应结果

但总归是做贼心虚,还是罢了。