参考链接: Python vars()

python+selenium定时爬取丁香园的新冠病毒每天的数据,并制作出类似的地图(部署到云服务器)

声明:仅供技术交流,请勿用于非法用途,如有其它非法用途造成损失,和本博客无关

目录

python+selenium定时爬取丁香园的新冠病毒每天的数据,并制作出类似的地图(部署到云服务器)前言一、准备二、爬取数据+画图第一步、分析页面第二步、编写代码第三步、结果展示

三、部署到云服务器1.定时运行获取数据2.通过微信获取地图(html文件)

四、运行展示

写在最后

前言

硬要说这篇文章怎么来的,那得先从那几个吃野味的人开始说起……前天睡醒:假期还有几天;昨天睡醒:假期还有十几天;今天睡醒:假期还有一个月……每天过着几乎和每个假期一样的宅男生活,唯一不同的是玩手机已不再是看剧、看电影、打游戏了,而是每天都在关注着这次新冠肺炎疫情的新闻消息,真得希望这场战“疫”快点结束,让我们过上像以前一样的生活。武汉加油!中国加油!!

本次爬取的网站是丁香园点击跳转,相信大家平时都是看这个的吧。

一、准备

python3.7selenium:自动化测试框架,直接pip install selenium安装即可pyecharts:以一切皆可配置而闻名的python封装的js画图工具,其官方文档写的很详细了点击跳转。直接pip install pyecharts安装即可,同时还需安装以下地图的包:

世界地图:pip install echarts-countries-pypkg中国地图:pip install echarts-china-provinces-pypkg中国城市地图:pip install echarts-china-cities-pypkg

云服务器

二、爬取数据+画图

第一步、分析页面

先用个requests模块请求一下,看能不能拿到数据:

import requests

url='https://ncov.dxy.cn/ncovh5/view/pneumonia_peopleapp?from=timeline&isappinstalled=0'

headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}

r=requests.get(url,headers=headers)

print(r.text)

发现数据是乱码的并且注意到末尾处有如下字样:

<noscript>You need to enable JavaScript to run this app.</noscript>

意思是需要执行js代码,百度了一下发现这个页面应该是用react.js来开发的。限于自身技术能力,这个时候,我就只能用selenium了,它是完全模拟浏览器的操作,也即能执行js代码。

并且我需要拿到的数据并不多,也就一个页面而已,所以耗时也可以接受。

那么我要拿哪些数据呢,如下:

截至当前时间的全国数据统计病毒相关描述信息全国各个省份及其城市的所有数据全世界各个地区的数据

经过查看,发现这几处需要进行点击,才能获取到更多数据信息:

第二步、编写代码

导入相关包:

from selenium import webdriver

from selenium.webdriver.common.action_chains import ActionChains

from selenium.webdriver.common.keys import Keys

import parsel

import time

import json

import os

import datetime

import pyecharts

from pyecharts import options as opts

定义爬取数据、保存数据的函数:

def get_save_data():

'''

部署到云服务器上时,注意:要安装pyvirtualdisplay模块,

并且把下面的前5条注释掉的代码给去掉注释,再运行,不然会报错。

'''

#from pyvirtualdisplay import Display

#display = Display(visible=0, size=(800, 600))

#display.start()

options=webdriver.ChromeOptions()

#options.add_argument('--disable-gpu')

#options.add_argument("--no-sandbox")

options.add_argument('--headless') #采用无头模式进行爬取

d=webdriver.Chrome(options=options)

d.get('https://ncov.dxy.cn/ncovh5/view/pneumonia_peopleapp?from=timeline&isappinstalled=0')

time.sleep(2)

ActionChains(d).move_to_element(d.find_element_by_xpath('//p[@class="mapTap___1k3MH"]')).perform()

time.sleep(2)

d.find_element_by_xpath('//span[@class="openIconView___3hcbn"]').click()

time.sleep(2)

for i in range(3):

mores=d.find_elements_by_xpath('//div[@class="areaBox___3jZkr"]')[1].find_elements_by_xpath('./div')[3:-1]

ActionChains(d).move_to_element(d.find_element_by_xpath('//div[@class="rumorTabWrap___2kiW4"]/p')).perform()

mores[i].click()

time.sleep(2)

response=parsel.Selector(d.page_source)

china=response.xpath('//div[@class="areaBox___3jZkr"]')[0]

world=response.xpath('//div[@class="areaBox___3jZkr"]')[1]

# 下面是病毒相关描述信息的获取与处理

content=response.xpath('//div[@class="mapTop___2VZCl"]/div[1]//text()').getall()

s=''

for i,j in enumerate(content):

s=s+j

if (i+1)%2 == 0:

s=s+'\n'

if j in ['确诊','疑似','重症','死亡','治愈']:

s=s+'\n'

now=s.strip()

msg=response.xpath('//div[@class="mapTop___2VZCl"]/div//text()').getall()

s=''

for i in msg:

if i not in now:

s=s+i+'\n'

msg=s.strip()

content=msg+'\n\n'+now

# 下面是全国数据的获取

china_data=[]

for div_list in china.xpath('./div')[2:-1]:

flag=0

city_list=[]

for div in div_list.xpath('./div'):

if flag == 0:

if div.xpath('./p[1]/text()').get() is not None:

item={}

item['省份']=div.xpath('./p[1]/text()').get()

item['确诊']=div.xpath('./p[2]/text()').get() if div.xpath('./p[2]/text()').get() is not None else '0'

item['死亡']=div.xpath('./p[3]/text()').get() if div.xpath('./p[3]/text()').get() is not None else '0'

item['治愈']=div.xpath('./p[4]/text()').get() if div.xpath('./p[4]/text()').get() is not None else '0'

flag=1

else:

if div.xpath('./p[1]/span/text()').get() is not None:

temp={}

temp['城市']=div.xpath('./p[1]/span/text()').get()

temp['确诊']=div.xpath('./p[2]/text()').get() if div.xpath('./p[2]/text()').get() is not None else '0'

temp['死亡']=div.xpath('./p[3]/text()').get() if div.xpath('./p[3]/text()').get() is not None else '0'

temp['治愈']=div.xpath('./p[4]/text()').get() if div.xpath('./p[4]/text()').get() is not None else '0'

city_list.append(temp)

item.update({'city_list':city_list})

china_data.append(item)

# 下面是全球数据的获取

world_data=[]

for div_list in world.xpath('./div')[2:-1]:

flag=0

country_list=[]

for div in div_list.xpath('./div'):

if flag == 0:

if div.xpath('./p[1]/text()').get() is not None:

item={}

item['地区']=div.xpath('./p[1]/text()').get()

item['确诊']=div.xpath('./p[2]/text()').get() if div.xpath('./p[2]/text()').get() is not None else '0'

item['死亡']=div.xpath('./p[3]/text()').get() if div.xpath('./p[3]/text()').get() is not None else '0'

item['治愈']=div.xpath('./p[4]/text()').get() if div.xpath('./p[4]/text()').get() is not None else '0'

flag=1

else:

if div.xpath('./p[1]/span/text()').get() is not None:

temp={}

temp['国家']=div.xpath('./p[1]/span/text()').get()

temp['确诊']=div.xpath('./p[2]/text()').get() if div.xpath('./p[2]/text()').get() is not None else '0'

temp['死亡']=div.xpath('./p[3]/text()').get() if div.xpath('./p[3]/text()').get() is not None else '0'

temp['治愈']=div.xpath('./p[4]/text()').get() if div.xpath('./p[4]/text()').get() is not None else '0'

country_list.append(temp)

item.update({'country_list':country_list})

world_data.append(item)

d.quit()

# 下面是保存数据的操作

if not os.path.exists('./json'):

os.makedirs('./json')

if not os.path.exists('./txt'):

os.makedirs('./txt')

now_time=datetime.datetime.now().strftime("%Y-%m-%d") #获取当前日期

index=list(range(len(china_data)))

data=dict(zip(index,china_data))

json_str = json.dumps(data, indent=4,ensure_ascii=False)

with open(f'./json/{now_time}.json', 'w', encoding='utf-8') as f:

f.write(json_str)

index=list(range(len(world_data)))

data=dict(zip(index,world_data))

json_str = json.dumps(data, indent=4,ensure_ascii=False)

with open(f'{now_time}.json', 'w', encoding='utf-8') as f:

f.write(json_str)

with open(f'./txt/{now_time}.txt', 'w', encoding='utf-8') as f:

f.write(content)

定义画地图的函数,输出是一个html文件:

def get_html():

# 首先是加载爬取到的数据

json_files=os.listdir('./json')

json_data=[]

date=[]

for i in json_files:

with open(f'./json/{i}','r',encoding='utf-8') as f:

date.append(i.split('.')[0])

temp=json.load(f)

json_data.append(list(temp.values()))

txt_files=os.listdir('./txt')

content_list=[]

for i in txt_files:

with open(f'./txt/{i}','r',encoding='utf-8') as f:

content_list.append(f.read())

# 下面开始画图

t=pyecharts.charts.Timeline(init_opts=opts.InitOpts(width='1400px',height='1400px',page_title='武汉加油!中国加油!!'))

for s,(i,data) in enumerate(zip(date,json_data)):

value=[] # 储存确诊人数

attr=[] # 储存城市名字

for each in data:

attr.append(each['省份'])

value.append(int(each['确诊']))

map0 = (

pyecharts.charts.Map()

.add(

series_name='该省份确诊数',data_pair=list(zip(attr,value)),maptype='china',is_map_symbol_show=True,zoom=1.1

)

.set_global_opts(title_opts=opts.TitleOpts(title="武汉加油!中国加油!!", # 标题

subtitle=content_list[s], # 副标题

title_textstyle_opts=opts.TextStyleOpts(color='red',font_size=30), # 标题文字

subtitle_textstyle_opts=opts.TextStyleOpts(color='black',font_size=20),item_gap=20), # 副标题文字

visualmap_opts=opts.VisualMapOpts(pieces=[{"max": 9, "min": 1,'label':'1-9','color':'#FFEBCD'},

{"max": 99, "min": 10,'label':'10-99','color':'#F5DEB3'},

{"max": 499, "min": 100,'label':'100-499','color':'#F4A460'},

{"max": 999, "min": 500,'label':'500-999','color':'#FA8072'},

{"max": 9999,"min": 1000,'label':'1000-9999','color':'#ee2c0f'},

{"min": 10000,'label':'≥10000','color':'#5B5B5B'}],

is_piecewise=True,item_width=45,item_height=30,textstyle_opts=opts.TextStyleOpts(font_size=20))

)

)

t.add(map0, "{}".format(i))

# 将这幅图保存为html文件

t.render('武汉加油!中国加油!!.html')

程序入口:

if __name__ == '__main__':

get_save_data()

get_html()

第三步、结果展示

运行该程序之后,会在当前目录下生成一个武汉加油!中国加油!!.html的文件,打开之后如下:  ps:因为只能上传图片,所以我就将html转为图片了,html是动态的,有时间轴可以拖动,由于昨天才刚开始爬数据,所以只有两天的数据。下面附上转图片的代码:

ps:又因为这个Timeline时间线轮播多图,配置不了背景颜色,发现生成的图片放大看变成黑色背景的,于是研究了一下源码,自己修改了一下js那块的代码,然后就生成可以设置背景颜色的图片了

from selenium import webdriver

import base64

import os

def decode_base64(data: str) -> bytes:

"""Decode base64, padding being optional.

:param data: Base64 data as an ASCII byte string

:returns: The decoded byte string.

"""

missing_padding = len(data) % 4

if missing_padding != 0:

data += "=" * (4 - missing_padding)

return base64.decodebytes(data.encode("utf-8"))

def save_as_png(image_data: bytes, output_name: str):

with open(output_name, "wb") as f:

f.write(image_data)

if __name__ == '__main__':

options=webdriver.ChromeOptions()

options.add_argument('--headless')

d=webdriver.Chrome(options=options)

url='file://'+os.path.abspath('武汉加油!中国加油!!.html')

d.get(url)

js = """

var ele = document.querySelector('div[_echarts_instance_]');

var mychart = echarts.getInstanceByDom(ele);

return mychart.getDataURL({

type: 'png',

pixelRatio: 2,

backgroundColor:'#FFFFFF',

excludeComponents: ['toolbox']

});

"""

content=d.execute_script(js)

content_array = content.split(",")

image_data = decode_base64(content_array[1])

save_as_png(image_data, '武汉加油!中国加油!!.png')

d.quit()

ps:还可以直接在源码里面修改,路径在D:\XXX\python3.7\Lib\site-packages\snapshot_selenium\snapshot.py,将里面的要执行的js代码改成如下:

SNAPSHOT_JS = """

var ele = document.querySelector('div[_echarts_instance_]');

var mychart = echarts.getInstanceByDom(ele);

return mychart.getDataURL({

type: '%s',

pixelRatio: %s,

backgroundColor:'#FFFFFF',

excludeComponents: ['toolbox']

});

"""

然后调用就简单了很多: 注意:修改源码后要重启python环境

from pyecharts.render import make_snapshot

from snapshot_selenium import snapshot

make_snapshot(snapshot,'武汉加油!中国加油!!.html','武汉加油!中国加油!!.png')

三、部署到云服务器

1.定时运行获取数据

首先将爬取数据的函数,即get_save_data()单独放到一个py文件中(我命名为:2019-nCoV.py)。然后修改定时任务/etc/crontab文件,如下:

2.通过微信获取地图(html文件)

把画地图的函数,即get_html()添加到个人微信机器人当中,然后设置特定判断条件,在手机微信上向文件传输助手发送设定好的指令,执行get_html()函数,然后把执行函数后生成的html文件发给文件传输助手,从而获取到当前的疫情地图。

个人微信机器人的代码我就不再展示了,可以看我之前的文章:python实现微信自动回复机器人+查看别人撤回的消息(部署到云服务器)

特定判断的语句如下:

if '2019' == msg['Text']:

get_html()

itchat.send('@fil@%s'%'武汉加油!中国加油!!.html',toUserName='filehelper')

同时,也可以把刚刚的获取数据的函数一起添加进去的,然后同样通过发送特定指令运行函数,而获取数据,我这里不加进去呢,是因为我要设置个定时任务,定时获取就行了;并且我也可以通过给文件传输助手发送shell命令,执行py文件。

把下面的代码加进个人微信机器人py文件里就行了。

import subprocess

def cmd(command):

output=subprocess.getoutput(command)

return output

并给出我的特定判断语句:

if 'cmd' in msg['Text']:

output=cmd(msg['Text'][3:])

if output != '':

itchat.send(output, toUserName='filehelper')

四、运行展示

如上图所示:我先是执行了爬取数据的函数,即我调用了云服务器上的定时爬取数据的py文件,然后再输入指令获取当前的疫情地图,打开后像上面的疫情地图一样。

写在最后

世界的疫情地图我没有画,是因为pyecharts的世界地图各个地区是用英文命名的,跟获取到的地区匹配不上,其实可以加个中文转英文给它,那就可以了,我懒的弄了,有兴趣的朋友可以试一试哦。不过我也把数据爬取下来了,这样以后想画的话也不至于连数据都没有哈哈

一开始,我只是在那些爬虫微信群上看到:今天这谁在爬丁香园的数据,过几天又看到那谁又在爬丁香园的数据,而且还提出各种问题来讨论。我实在是看不下去了,于是就有了这一篇文章(反正在家闲着也是闲着)

然后呢,今天学校发通知说校外的大四学生也可以申请vpn,然后在家就可以查看和下载知网的文献了。准备毕业的我突然惊了,我的论文还未开始写呢!看来是时候了……

其实我是想回学校再写的,但是这次的新冠肺炎疫情来势凶猛,真的希望快点好起来啊~

武汉加油!中国加油!!

[转载] python+selenium定时爬取丁香园的新冠病毒每天的数据,并制作出类似的地图(部署到云服务器)相关推荐

  1. python+selenium定时爬取丁香园的新冠病毒每天的数据,并制作出类似的地图(部署到云服务器)

    python+selenium定时爬取丁香园的新冠病毒每天的数据,并制作出类似的地图(部署到云服务器) 声明:仅供技术交流,请勿用于非法用途,如有其它非法用途造成损失,和本博客无关 目录 python ...

  2. Python爬虫笔记(3)- 爬取丁香园留言

    Python爬虫笔记(3)- 爬取丁香园留言 爬取丁香园留言:主要用到了模拟登录 爬取丁香园留言:主要用到了模拟登录 import requests, json, re, random,time fr ...

  3. 利用paddlepaddle爬取丁香园实时统计数据,并生成疫情地图!!

    当下,新型冠状病毒感染的肺炎疫情无时无刻不牵动着人们的心.面对来势汹汹的疫情,除了奋战在前线的医护人员以及防疫建设工作者们,小媛们也想尽一份绵薄之力. 这不,今天为大家带来了一份超超超简单的!生成自己 ...

  4. python + selenium多进程爬取淘宝搜索页数据

    python + selenium多进程爬取淘宝搜索页数据 1. 功能描述 按照给定的关键词,在淘宝搜索对应的产品,然后爬取搜索结果中产品的信息,包括:标题,价格,销量,产地等信息,存入mongodb ...

  5. 爬虫(2)之 Xpath(爬取丁香园)

    Xpath常用的路径表达式: XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言. 在XPath中,有七种类型的节点:元素.属性.文本.命 ...

  6. 爬虫 -----beautifulsoup、Xpath、re (二)附爬取丁香园用户名以及回复内容

    目录 1.Xpath简介 1.1使用流程: 1.2Xpath常用的路径表达式 1.3 使用lxml解析 2 实战:爬取丁香园-用户名和回复内容 2.1 获取url的html 2.2 lxml解析htm ...

  7. python + selenium +chrome爬取qq空间好友说说并存入mongodb数据库

    python + selenium +chrome爬取qq空间好友说说并存入mongodb数据库 准备阶段 在正式开始在前需要先准备好做爬虫的工具,本例使用chrome无头浏览器进行爬取工作,也可使用 ...

  8. python+selenium+phantomJS爬取国家地表水水质自动监测实时数据发布系统——动态网页爬虫

    一.关于phantomjs 1.介绍 PhantomJS是一个为自动化而生的利器,它本质上是一个基于webkit内核的无界面浏览器,并可使用JavaScript或CoffeeScript进行编程.由于 ...

  9. 爬取并处理中国新冠肺炎疫情数据

    项目名称: 爬取并处理中国新冠肺炎疫情数据 目的: 通过Python爬取中国新冠肺炎疫情数据,存入Excel,对此数据分析并进行可视化,制作查询中国疫情情况的GUI界面. 具体内容: 通过Python ...

最新文章

  1. 腾讯云携手SENSORO,为城市安全保驾护航
  2. 网络营销外包——网络营销外包新手如何理解优化对网络营销的重要性?
  3. 认清差距,抓住人工智能历史机遇
  4. 动窗口的制作暨CSizingControlBar类的使用说明
  5. BXUG第11期活动
  6. SVN 批量添加文件到版本库的命令脚本
  7. h5微信本地调试 vue_vueh5中使用微信sdk
  8. 信息学奥赛C++语言:奖励钢笔
  9. bp算法运行太慢_神经网络,BP算法的理解与推导
  10. VoIP之语音编码器
  11. pku1159 Palindrome(简单dp)
  12. oracle pivot 去除引号,使用pivot显示列式统计结果实例
  13. pytorch visdom可视化工具学习—1—详细使用-3-Generic Plots和Others
  14. 合肥青少年信息学计算机竞赛试题,合肥市第二十九届青少年信息学奥林匹克竞赛(小学组)试题及部分答案...
  15. 推荐一本好书《代码整洁之道 (claen code) 》
  16. 如何给扑克洗牌才能更公平?
  17. 如何恢复按下Shift + DELETE键永久删除的文件和资料夹?
  18. python音频处理库librosa基本操作
  19. VS2019编译python解释器源码及学习方法
  20. 用树莓派DIY波士顿机器狗,帮你省下50万:教程开源,人人皆可上手

热门文章

  1. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明),签到题J Parallel Sort
  2. 【NOIP2015】【Luogu2670】扫雷游戏(搜索,字符串输入输出)
  3. 【NOIP2000】【Luogu1019】单词接龙
  4. MySQL→数据库、启动连接数据库、SQL→DDL数据定义语言及数据类型、DML数据操作语言、DQL数据查询语言、数据库约束→主键、唯一、非空、默认、外键、SQL、三大范式及一多关系、视图、内外连接
  5. 剑指offer -- 反转链表
  6. lua游戏脚本实例源码_Redis Lua脚本中学教程(上)
  7. 计算机网络—GBN协议(后退N帧协议)
  8. oracle当前用户创建的表不可见?
  9. 拆点并查集(poj 1182: 食物链)
  10. 拟阵:贪心原理(bzoj 3105: [cqoi2013]新Nim游戏)