爬空气质量MySQL_爬虫:利用selenium采集某某环境网站的空气质量数据

前言:在上一篇文章中,我们介绍了在http://PM2.5.in这个网站采集空气质量的数据,本篇文章是对其产生的一些问题的另一种解决方案,提供更加权威的数据采集。

技术框架:selenium、json、etree

这里的selenium是一种自动化测试的工具,它可以帮助我们模拟浏览器打开网页并获取网页数据,本文之所以选择这种方式进行,是因为以requests方式直接请求无法获取到正确的数据,这个网页的数据是动态加载,需要用户执行点击操作才会被请求

我们还是按照常规套路来分析下这个网站,打开F12,看下这个网站的数据请求

可以发现这个网站的数据的请求接口,但当我们直接用requests去请求这个接口,会发现无法获取正确的数据,原因是这个网站采用了MmEwMD这个值进行了反爬虫,这个是一个比较常见的反爬虫措施,他这个值是在发起请求时动态生成的,最简单的解决这个问题的办法就是采用selenium之类的模拟浏览器方法进行请求,这样的话,发出的请求也会自动带上这个参数

请求的代码如下图所示

driverPath = 'browser\\chromedriver.exe'

options = webdriver.ChromeOptions()

options.add_experimental_option("excludeSwitches", ["enable-automation"])

options.add_experimental_option('useAutomationExtension', False)

# options.add_argument(('--proxy-server=http://' + ip))

browser = webdriver.Chrome(options=options, executable_path=driverPath)

browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {

"source": """

Object.defineProperty(navigator, 'webdriver', {

get: () => undefined

})

"""

})

browser.get(self.url)

html = browser.page_source

browser.quit()

# print(html)

reponse = etree.HTML(html)

data = reponse.xpath('//body/text()')[0]

json_data = json.loads(data)

我们通过调用谷歌浏览器直接请求对应的页面,获取到数据后,关闭浏览器,通过etree解析网页结果,通过观察发现,我们获取到的数据是json数组,因此我们使用json解析数据,然后将对应的数据存储到数据库

result_list = json_data['data']['hour']

print(result_list)

for result in result_list:

item = dict()

item['affect'] = result['AFFECTINFO']

item['action'] = result['SUGGEST']

if('AQIPRIMPOLLUTE' in result):

item['primary_pollutant'] = result['AQIPRIMPOLLUTE']

else:

item['primary_pollutant'] = '无'

item['AQI'] = result['AQI']

item['PM2.5/1h'] = result['PM25']

item['PM10/1h'] = result['PM10']

item['CO/1h'] = result['CO']

item['NO2/1h'] = result['NO2']

item['O3/1h'] = result['O3']

item['O3/8h'] = result['O3_2']

item['SO2/1h'] = result['SO2']

item['city_name'] = result['POINTNAME']

item['level'] = result['CODEAQILEVEL']+'('+result['AQILEVELNAME']+')'

item['live_data_time'] = result['MONITORTIME']

item['live_data_time'] = datetime.datetime.strptime(item['live_data_time'], "%Y年%m月%d日%H")

update_time = item['live_data_time'].strftime('%Y-%m-%d %H:%M:%S')

item['live_data_unit'] = 'μg/m3(CO为mg/m3)'

if(item['city_name'] in city_config):

self.save_mysql(item)

success_count = success_count+1

log_text = '采集的城市:{},采集的结果:{}'.format(item['city_name'],'成功')

self.save_log({'log_type':'0','log_text':log_text})

self.save_log({'log_type':'3','log_text':log_text})

self.update_spider_time(update_time)

# 存储运行日志

def save_log(self,item):

sql = 'INSERT INTO log(log_text,log_type,created_time) VALUES (%s,%s,%s)'

values = [item['log_text'],item['log_type'],datetime.datetime.now()]

self.cursor.execute(sql,values)

self.conn.commit()

def save_mysql(self,item):

# 查询数据库已存在的数据

query_sql = 'select count(1) as count from kongqizhiliang where city_name= %s and live_data_time = %s'

values = [item['city_name'],item['live_data_time']]

self.cursor.execute(query_sql,values)

data = self.cursor.fetchone()

# 如果不存在同一城市同一时刻更新的数据,则新增

if(data['count'] == 0):

sql = ("INSERT kongqizhiliang(city_name,level,live_data_time,live_data_unit,AQI,PM25_1h,PM10_1h,CO_1h"

",NO2_1h,O3_1h,O3_8h,SO2_1h,affect,primary_pollutant,action"

") VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)")

values =[item['city_name'],item['level'],item['live_data_time'],item['live_data_unit'],item['AQI']

,item['PM2.5/1h'],item['PM10/1h'],item['CO/1h'],item['NO2/1h'],item['O3/1h'],item['O3/8h']

,item['SO2/1h'],item['affect'],item['primary_pollutant'],item['action']]

self.cursor.execute(sql,values)

self.conn.commit()

其实当初这个反爬虫措施也困扰了我一段时间的,我这里采用的是最简单的方法解决,虽然效率不高,但能解决我的需求

完整代码如下:其中部分代码是可以不需要的,必须redis和config那个,你们自己改一下,不会的可以问我,这个是当时给别人毕设做的,还有其他功能,所以会有一些其他的

"""

采集空气质量的数据

目标网站:http://sthjt.hubei.gov.cn/hjsj/

"""

import requests

from lxml import etree

import re

from xpinyin import Pinyin

import pymysql

import sys

from settings.config import *

from utils import RedisUtil

import datetime

import json

from selenium import webdriver

class kongqizhiliang:

DEFAULT_REQUEST_HEADERS = {

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',

'Accept-Language': 'en',

'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'

}

url = 'http://sthjt.hubei.gov.cn/wcmapi/service/aqi.xhtml'

redis_key = 'kongqi:config_city'

update_time = 'kongqi:update_time'

# 汉字转拼音

pinyin = Pinyin()

def __init__(self):

self.conn = pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=db, charset=charset)

self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)

# 将城市名转化为code

def get_code(self,city_name):

return self.pinyin.get_pinyin(city_name, '' )

def get_city_config(self):

redis_util = RedisUtil.get_redis()

city_list = redis_util.list_get_range(self.redis_key)

return city_list

def update_spider_time(self,update_time):

redis_util = RedisUtil.get_redis()

redis_util.str_set(self.update_time,update_time)

def get_data(self):

city_config = self.get_city_config()

log_text = '采集开始,准备采集的城市:{},计划采集的数据量:{}'.format(city_config,len(city_config))

self.save_log({'log_type':'2','log_text':log_text})

success_count = 0

update_time = ''

driverPath = 'browser\\chromedriver.exe'

options = webdriver.ChromeOptions()

options.add_experimental_option("excludeSwitches", ["enable-automation"])

options.add_experimental_option('useAutomationExtension', False)

# options.add_argument(('--proxy-server=http://' + ip))

browser = webdriver.Chrome(options=options, executable_path=driverPath)

browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {

"source": """

Object.defineProperty(navigator, 'webdriver', {

get: () => undefined

})

"""

})

browser.get(self.url)

html = browser.page_source

browser.quit()

# print(html)

reponse = etree.HTML(html)

data = reponse.xpath('//body/text()')[0]

json_data = json.loads(data)

# print(json_data)

result_list = json_data['data']['hour']

print(result_list)

for result in result_list:

item = dict()

item['affect'] = result['AFFECTINFO']

item['action'] = result['SUGGEST']

if('AQIPRIMPOLLUTE' in result):

item['primary_pollutant'] = result['AQIPRIMPOLLUTE']

else:

item['primary_pollutant'] = '无'

item['AQI'] = result['AQI']

item['PM2.5/1h'] = result['PM25']

item['PM10/1h'] = result['PM10']

item['CO/1h'] = result['CO']

item['NO2/1h'] = result['NO2']

item['O3/1h'] = result['O3']

item['O3/8h'] = result['O3_2']

item['SO2/1h'] = result['SO2']

item['city_name'] = result['POINTNAME']

item['level'] = result['CODEAQILEVEL']+'('+result['AQILEVELNAME']+')'

item['live_data_time'] = result['MONITORTIME']

item['live_data_time'] = datetime.datetime.strptime(item['live_data_time'], "%Y年%m月%d日%H")

update_time = item['live_data_time'].strftime('%Y-%m-%d %H:%M:%S')

item['live_data_unit'] = 'μg/m3(CO为mg/m3)'

if(item['city_name'] in city_config):

self.save_mysql(item)

success_count = success_count+1

log_text = '采集的城市:{},采集的结果:{}'.format(item['city_name'],'成功')

self.save_log({'log_type':'0','log_text':log_text})

self.save_log({'log_type':'3','log_text':log_text})

self.update_spider_time(update_time)

# 存储运行日志

def save_log(self,item):

sql = 'INSERT INTO log(log_text,log_type,created_time) VALUES (%s,%s,%s)'

values = [item['log_text'],item['log_type'],datetime.datetime.now()]

self.cursor.execute(sql,values)

self.conn.commit()

def save_mysql(self,item):

# 查询数据库已存在的数据

query_sql = 'select count(1) as count from kongqizhiliang where city_name= %s and live_data_time = %s'

values = [item['city_name'],item['live_data_time']]

self.cursor.execute(query_sql,values)

data = self.cursor.fetchone()

# 如果不存在同一城市同一时刻更新的数据,则新增

if(data['count'] == 0):

sql = ("INSERT kongqizhiliang(city_name,level,live_data_time,live_data_unit,AQI,PM25_1h,PM10_1h,CO_1h"

",NO2_1h,O3_1h,O3_8h,SO2_1h,affect,primary_pollutant,action"

") VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)")

values =[item['city_name'],item['level'],item['live_data_time'],item['live_data_unit'],item['AQI']

,item['PM2.5/1h'],item['PM10/1h'],item['CO/1h'],item['NO2/1h'],item['O3/1h'],item['O3/8h']

,item['SO2/1h'],item['affect'],item['primary_pollutant'],item['action']]

self.cursor.execute(sql,values)

self.conn.commit()

if __name__ == "__main__":

app = kongqizhiliang()

app.get_data()

本文首发于爬虫:利用selenium采集某某环境网站的空气质量数据​www.bizhibihui.come61b8d8ca1d5a096c1552def544a391a.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559199.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql导出数据意义_11、mysql导出数据

1、使用select... into outfile语句导出数据(1)txt格式select *from runoob.tb1 into outfile /tmp/runoob.txt;(2)CSV格式select * from passwd into outfile /tmp/runoob.txt fields terminated by , enclosed by " lines terminated by \r\n;(3)生成一种文件&#xff0…

操作失败10秒内未完成启动服务mysql_01-MySQL 命令行-cmd用法-未完成

01.png02.png03.png04.png05.png06.png07.png08.png09.png一、mysql服务的启动和停止net stop mysqlnet start mysql二、登陆mysql语法如下: mysql -u用户名 -p用户密码键入命令mysql -uroot -p, 回车后提示你输入密码,输入12345,…

java时间聚类_mongodb 按照时间聚类 java

当存储到mongodb中的是string类型的时间,小tips:1. 那么在对此域按照时间聚类(每周,每月)时就不能直接使用mongodb的time关键字了,因为mongodb有自己的时间类型,且目前它只认可自己的时间类型。2. 假如对于时间进行简单的聚类&…

selenium python实例录制运行_WEB自动化测试工具selenium录制器使用笔记

简介selenium录制器是最近刚流行起来的一个WEB自动化测试工具,由多测测团队开发。Selenium录制器采用关键字驱动的理念,简化测试用例的创建和维护,可以直接运行在浏览器中,就像真正的用户在操作一样。自动化脚本录制、一键回放、报…

cass坡度土方计算案例_60度斜坡怎么计算_南方CASS土方计算方法—方格网法

01概述在我们的日常工作中,遇到大量的土方修正算的相关咨询,为什么CASS的方格网土方修正算,方格设定为10米和20米,修正算结果有很大差异呢?从软件计算原理、数据质量等方面进行分析,读了这篇文章&#xff0…

java ssh cpu_初学Java ssh之Spring 第四篇

今天我来学习学习Spring中Bean。在Spring中原来还有标签啊,它相当于标签的老爸,老爸可以有很多个儿子,但是老爸只有一个哦。也就是说一个标签内可以有多个标签,每个标签代表一个java实例。定义时,需要注意两个属性&…

java中servlet知识_jsp_Servlet常用知识总结

Servlet三个要素[java] view plain copy print?1.必须继承自HttpServlet2.必须实现doGet()或者doPost()3.必须在web.xml中配置ServletHttpServeltRrequest:请求对象getParameter():获得表单元素的值getAttribute():获得request范围中的属性值setAttribute():设置reqeust范围中…

java语言执行模式,使用java.exe执行静默模式

I would like to know if there is a way to execute the "java.exe" as a background process (silent mode execution)Ex: java -cp . MyClass arg1I want to run the above statement as a background process , without opening command window解决方案Under Win…

linux下tomcat部署java web项目_求助帖 linux服务器 tomcat部署javaweb项目问题

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼03-Sep-2018 17:42:07.330 SEVERE [localhost-startStop-1] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start:org.apache.catalina.LifecycleException: Failed to start component [Stan…

rabbitmq+topic+java_译:5.RabbitMQ Java Client 之 Topics (主题)

我们使用的是direct(直接交换),而不是使用只能进行虚拟广播的 fanout(扇出交换),并且有可能选择性地接收日志。虽然使用direct(直接交换)改进了我们的系统,但它仍然有局限性 - 它不能基于多个标准进行路由。在我们的日志系统中,我…

java某个时间推迟60天_java计算两个时间相差(天、小时、分钟、秒)

public static long dateDiff(String startTime, String endTime,String format, String str) {// 按照传入的格式生成一个simpledateformate对象SimpleDateFormat sd new SimpleDateFormat(format);long nd 1000 * 24 * 60 * 60;// 一天的毫秒数long nh 1000 * 60 * 60;// …

java影碟租赁系统_java影碟管理系统

在学习基于javaweb的影碟管理系统项目的时候,方便日后能及时查阅,在本平台中记录一下基于javaweb的影碟管理系统的开发流程。在学习时候的选用了SSM(MYECLIPSE),这个框架不论是学习还是使用都非常方便,简单易上手。基于javaweb的影碟管理系统…

hasp 加密 java_加密软件HASP的使用说明

加密软件hasp使用说明1.hasp环境的搭建hasp环境的搭建要根据机器的环境来安装,①windows系统的就安装windows版本,安装步骤可以参考<录像>文件下里的hasp5.0系统安装.exe;②linux版本的需要安装linux版本,安…

java明文发送_使用java MD5加密网络明文

1.[代码][Java]代码import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;/*** Created by liuhj on 2015/11/27.*/public class MD5 {public static void main(String args[]){StringMD5("123456");}public static String StringMD5(…

php设置session 生命周期,设置session的生命周期(php)

PHP中,Session变量保存在服务器端(默认以文件格式保存),而Session ID以cookie形式保存在客户端。销毁session的方法有2种第一种是通过程序session_destory()方法清除所有sessionunset(session[x])来清除指定的session[x]。第二种是通过关闭浏览器关闭后会…

php 查找无限级,Ztree + PHP 无限级节点 递归查找节点法

一、前言简单的描述一下,实习几个原理,思想,其实写很多东西,思想算是最重要的。1、目标:将写一个无限节点的树形目录结构,如下图步骤:1、你的下载 插件 ztree。然后布置在你的项目中。2、相关C…

用php实现一个简易的web表单生成器,网络编程PHP Web表单生成器案例分析

本文实例讲述了PHP Web表单生成器。分享给大家供大家参考,具体如下:1.实例:2. 需求分析在项目的实际开发中,经常需要设计各种各样表单。直接编写HTML表单虽然简单,但修改、维护相对麻烦。因此,可以利用PHP实…

php瀑布墙,phpwind Next增加“瀑布流”图墙展示模式

近日,化龙巷网站CEO钱钰在微博上爆出phpwind最新版本的部分截图,引发行业关注。据悉,该版本或命名“Next”,目前,phpwind官方暂未对外披露新版本相关信息,也未公布项目的进展。从流传的产品首页效果图来看,…

管理员信息模块php,管理员模块功能代码

摘要&#xff1a;<?php /*** Created by PhpStorm.* User: Administrator* Date: 2019/5/10* Time: 10:12*/namespace app\admin\contro<?php /*** Created by PhpStorm.* User: Administrator* Date: 2019/5/10* Time: 10:12*/namespace app\admin\controller;use app…

php项目的建立,PHP开发-ZendStudio初学教程-建立PHP项目

英文描述Project Name: Enter the name of your project.Location: Enter the location folder for your project.PHP Server :- Click the drop-down menu and select an existing server for deploying the new server project, or click Add Server to create a new server.…