欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python每天自动爬取所需新冠肺炎疫情数据并发送到邮箱(无需selenium)

程序员文章站 2022-04-09 12:51:02
...

python每天自动爬取所需新冠肺炎疫情数据并发送到邮箱

一、前言

这个寒假真是又长又无聊,我大概有两个星期没出门了。为了给自己找点事做,这两天弄了个爬虫玩玩,有不严谨的地方望大家指教。

二、项目简介

这次项目主要是想做一个爬虫,可以每天早上定时爬取当天的疫情数据,然后把数据发到我的邮箱里,让自己可以一大早醒来就实时了解到最新情况。为了简单起见,我只爬取湖北武汉,海南海口,江苏南京三个省市,一个是疫情主要战场,一个是我目前居住地,一个是我学校所在地。当然原理都是一样的,大家想爬取别的地方也可以。

三、原理

整个项目分成三个部分,第一部分是爬虫部分,第二部分是邮件部分,第三部分是云服务器部分,接下来我会一一介绍。

1、爬虫

这里我用到的库如下:

import urllib
from bs4 import BeautifulSoup
import json

urllib是用来获取网站源码的,bs4是用来解析html标签的,解析完后得到的是字符串,所以又用了json来转化成列表。

数据源我选用的是丁香园的,网站上相关数据显示的是这样:
python每天自动爬取所需新冠肺炎疫情数据并发送到邮箱(无需selenium)
我们来看看源码中的相关部分:

python每天自动爬取所需新冠肺炎疫情数据并发送到邮箱(无需selenium)
可以看到各个地区的数据被放在了id为“getAreaStat”的script标签里,通过findAll方法可以很容易定位到。

html = urllib.urlopen("https://ncov.dxy.cn/ncovh5/view/pneumonia?scene=2&clicktime=1579582238&enterid=1579582238&from=singlemessage&isappinstalled=0")
soup = BeautifulSoup(html.read())

block = soup.findAll("script",{"id":"getAreaStat"})
block0 = block[0]
blo_text = block0.get_text()
goal_text = blo_text[27:-11]

这里返回的block是bs4.element.ResultSet类型的,block0是bs4.element.Tag类型的,我们需要的是第二个(这里我对bs4的学习也还不够深入没法讲的太仔细)。然后再提取它的text部分即得到了一列字符串,这个字符串里是我们要的对于每一个省份数据的列表,但是头尾有一些我们不要的字符串,要把它掐掉,就可以得到goal_text。

然后用json将这个字符串转化成列表类型。

goal_list = json.loads(goal_text)

这个列表有34个元素,对应34个省直辖市特别行政区,每一个元素又是一个字典,包括某个省的名称、确诊人数、市等等,市的索引值又是一个列表,对应不同市,列表里面又是一个字典…

总之,理清它的数据结构我们就能通过遍历找到我们想要的省市数据。

for i in range(len(goal_list)):#这里用的是中文的unicode编码
    if(goal_list[i]['provinceShortName']==u'\u6e56\u5317'):
        hubei_num = i #湖北
    if(goal_list[i]['provinceShortName']==u'\u6d77\u5357'):
        hainan_num = i #海南
    if(goal_list[i]['provinceShortName']==u'\u6c5f\u82cf'):
        jiangsu_num = i #江苏

#三个省的确诊人数
hubei_confirmedCount = goal_list[hubei_num]['confirmedCount']
hainan_confirmedCount = goal_list[hainan_num]['confirmedCount']
jiangsu_confirmedCount = goal_list[jiangsu_num]['confirmedCount']

#武汉
for i in range(len(goal_list[hubei_num]['cities'])):
    if(goal_list[hubei_num]['cities'][i]['cityName']==u'\u6b66\u6c49'):
        wuhan_num = i
wuhan_confirmedCount = goal_list[hubei_num]['cities'][wuhan_num]['confirmedCount']

#海口
for i in range(len(goal_list[hainan_num]['cities'])):
    if(goal_list[hainan_num]['cities'][i]['cityName']==u'\u6d77\u53e3'):
        haikou_num = i
haikou_confirmedCount = goal_list[hainan_num]['cities'][haikou_num]['confirmedCount']

#南京
for i in range(len(goal_list[jiangsu_num]['cities'])):
    if(goal_list[jiangsu_num]['cities'][i]['cityName']==u'\u5357\u4eac'):
        nanjing_num = i
nanjing_confirmedCount = goal_list[jiangsu_num]['cities'][nanjing_num]['confirmedCount']


2、邮件

发邮件的代码比较套路了,这里就简单介绍一下。

用到的就两个库(smtplib,email),一个是负责传输协议,发送邮件,一个是用来编写邮件。

import smtplib
from email.mime.text import MIMEText
from email.header import Header

先编写邮件内容,这里邮件的内容我写的是html格式,为了好看一点。

message = MIMEText('<html><body><h1>今日疫情</h1>' +
                   '<p><b>湖北确诊人数:'+str(hubei_confirmedCount) + '</b>' +
                   '<br>&nbsp;&nbsp;&nbsp;&nbsp;武汉确诊人数:'+str(wuhan_confirmedCount) + '</p>' +
                   '<p><b>海南确诊人数:'+str(hainan_confirmedCount) + '</b>' +
                   '<br>&nbsp;&nbsp;&nbsp;&nbsp;海口确诊人数:'+str(haikou_confirmedCount) + '</p>' +
                   '<p><b>江苏确诊人数:'+str(jiangsu_confirmedCount) + '</b>' +
                   '<br>&nbsp;&nbsp;&nbsp;&nbsp;南京确诊人数:'+str(nanjing_confirmedCount) + '</p>' +
                   '</body></html>','html','utf-8')

然后发送邮件四部曲。

server = smtplib.SMTP()
server.connect('smtp.qq.com',587) #smtp服务器和端口,端口是固定的
server.login(from_addr,'xxx') #第二个参数是邮箱授权码,需要自己去邮箱里找
server.sendmail(from_addr,to_addr,message.as_string()) #发送邮箱地址和接收邮箱地址都是我的地址

其他细枝末节的代码参见第四部分完整代码。

3、云服务器

为了让程序能每天准时自动运行,需要挂到云服务器上,这里我用的是阿里云的学生云服务器,价格便宜也够用。

定时运行程序步骤如下:
控制面板→系统和安全→管理工具→计划任务
python每天自动爬取所需新冠肺炎疫情数据并发送到邮箱(无需selenium)
→任务计划程序(本地)→任务计划程序库→创建任务
python每天自动爬取所需新冠肺炎疫情数据并发送到邮箱(无需selenium)
然后写任务名称,触发器条件和执行操作,就行了。其中执行操作可以参考我这么填:
python每天自动爬取所需新冠肺炎疫情数据并发送到邮箱(无需selenium)

四、完整代码

-*- coding: UTF-8 -*-

import urllib
from bs4 import BeautifulSoup
import json
import smtplib
from email.mime.text import MIMEText
from email.header import Header


html = urllib.urlopen("https://ncov.dxy.cn/ncovh5/view/pneumonia?scene=2&clicktime=1579582238&enterid=1579582238&from=singlemessage&isappinstalled=0")
soup = BeautifulSoup(html.read())

block = soup.findAll("script",{"id":"getAreaStat"})
block0 = block[0]
blo_text = block0.get_text()
goal_text = blo_text[27:-11]

#goal_list = eval(goal_text.decode())
goal_list = json.loads(goal_text)

for i in range(len(goal_list)): #这里用的是中文的unicode编码
    if(goal_list[i]['provinceShortName']==u'\u6e56\u5317'):
        hubei_num = i #湖北
    if(goal_list[i]['provinceShortName']==u'\u6d77\u5357'):
        hainan_num = i #海南
    if(goal_list[i]['provinceShortName']==u'\u6c5f\u82cf'):
        jiangsu_num = i #江苏

#三个省的确诊人数
hubei_confirmedCount = goal_list[hubei_num]['confirmedCount']
hainan_confirmedCount = goal_list[hainan_num]['confirmedCount']
jiangsu_confirmedCount = goal_list[jiangsu_num]['confirmedCount']

#武汉
for i in range(len(goal_list[hubei_num]['cities'])):
    if(goal_list[hubei_num]['cities'][i]['cityName']==u'\u6b66\u6c49'):
        wuhan_num = i
wuhan_confirmedCount = goal_list[hubei_num]['cities'][wuhan_num]['confirmedCount']

#海口
for i in range(len(goal_list[hainan_num]['cities'])):
    if(goal_list[hainan_num]['cities'][i]['cityName']==u'\u6d77\u53e3'):
        haikou_num = i
haikou_confirmedCount = goal_list[hainan_num]['cities'][haikou_num]['confirmedCount']

#南京
for i in range(len(goal_list[jiangsu_num]['cities'])):
    if(goal_list[jiangsu_num]['cities'][i]['cityName']==u'\u5357\u4eac'):
        nanjing_num = i
nanjing_confirmedCount = goal_list[jiangsu_num]['cities'][nanjing_num]['confirmedCount']



#################################################email


from_addr = 'aaa@qq.com'
to_addr = 'aaa@qq.com'

message = MIMEText('<html><body><h1>今日疫情</h1>' +
                   '<p><b>湖北确诊人数:'+str(hubei_confirmedCount) + '</b>' +
                   '<br>&nbsp;&nbsp;&nbsp;&nbsp;武汉确诊人数:'+str(wuhan_confirmedCount) + '</p>' +
                   '<p><b>海南确诊人数:'+str(hainan_confirmedCount) + '</b>' +
                   '<br>&nbsp;&nbsp;&nbsp;&nbsp;海口确诊人数:'+str(haikou_confirmedCount) + '</p>' +
                   '<p><b>江苏确诊人数:'+str(jiangsu_confirmedCount) + '</b>' +
                   '<br>&nbsp;&nbsp;&nbsp;&nbsp;南京确诊人数:'+str(nanjing_confirmedCount) + '</p>' +
                   '</body></html>','html','utf-8')

message['From'] = Header(from_addr)
message['To'] = Header(to_addr)
message['Subject'] = Header(u'新冠肺炎疫情自动通报')

server = smtplib.SMTP()
server.connect('smtp.qq.com',587) #smtp服务器和端口,端口是固定的
server.login(from_addr,'xxx') #第二个参数是邮箱授权码,需要自己去邮箱里找
server.sendmail(from_addr,to_addr,message.as_string())

server.quit()


五、结果展示

python每天自动爬取所需新冠肺炎疫情数据并发送到邮箱(无需selenium)

相关标签: 爬虫 python