前言:在上一篇文章中,我们介绍了在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.com

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

  1. python爬火车票是不是违法_python利用selenium+requests+beautifulsoup爬取12306火车票信息...

    在高速发展的时代.乘车出远门是必不可少的,有些查询信息是要收费的.这里打造免费获取火车票信息 想要爬取12306火车票信息,访问12306官方网站,输入出发地,目的地  ,时间  之后点击确定,这是我 ...

  2. 【学习】03 淘宝爬虫-使用selenium采集关键词为电动车的数据

    参考: 静觅丨崔庆才的个人博客 项目地址: copywang/spiders_collection 实现功能: 使用geckodriver驱动firefox访问淘宝首页,输入关键词,点击搜索按钮,翻页 ...

  3. python爬虫实战笔记——爬取图书信息(利用selenium库+chromedriver.exe插件)

    准备: 1.插件chromedriver.exe 2.已经安装好谷歌浏览器Chrome 编写代码 from bs4 import BeautifulSoup from selenium import ...

  4. 前程无忧51job爬虫利用selenium爬取岗位信息-2021年10月29日

    # 2021年10月29日完成,爬取51job网站获得相关岗位信息 from selenium import webdriver from selenium.webdriver import Fire ...

  5. python之爬虫神器selenium:猫眼电影榜单并进行数据可视化

    如果你在学习爬虫,那么你一定爬取过豆瓣或猫眼电影的榜单,但大多数教程都是用的requests+正则,但对于很多新手来讲,requests获取网页容易,但是用正则表达式解析网页就难的多了.那么,让我们告 ...

  6. Anaconda3 安装 爬虫库 selenium(windows环境)

    一.Anaconda 安装selenium库 #使用命令:conda或pip conda install seleniumpip install selenium 用 Chrome 浏览器来测试 #用 ...

  7. 利用selenium自动抓取淘宝后台运营数据填入表格

    在下帮别人写的简单python程序.我很懒,有时间再写博客,先放github链接吧 使用说明: 一.电脑环境配置 电脑:windows系统: 浏览器:谷歌,建议版本 95.0.4638.69(如果其他 ...

  8. 【毕业设计_课程设计】基于网络爬虫的新闻采集和订阅系统的设计与实现(源码+论文)

    文章目录 0 项目说明 1 项目说明 2 系统需求 3 系统架构 4 效果展示 5 论文目录 6 项目工程 0 项目说明 基于网络爬虫的新闻采集和订阅系统的设计与实现 提示:适合用于课程设计或毕业设计 ...

  9. python网络爬虫——使用selenium抓取东方财富网上市公司公告

    每日公告数量@TOC 一.数据获取与预处理 本文从东方财富网上市公司公告页面获取沪深A股1991-2019年公告数据,按照数据获取的先后顺序,将数据分为以下两个部分一是上市公司公告信息,包括:序号(i ...

最新文章

  1. php yii gridview字符串截取,Yii2-GridView常用代码块、笔记
  2. linux在文档中查找内容,【Linux】用grep在文档中查找内容
  3. 虚拟服务器至强,用至强解决瓶颈 桌面虚拟化案例分享
  4. (转)博弈 SG函数
  5. 李洪强iOS经典面试题36-简单介绍 ARC 以及 ARC 实现的原理
  6. python操作access数据库未发现数据源名称_ASP连接ACCESS数据库失败,提示“未发现数据源名称并且未指定默认驱动程序”...
  7. 淘宝弹性布局方案lib-flexible实践
  8. 4键电子手表说明书_数字S1系统7寸门口主机操作说明书
  9. 力扣1175.质数排列
  10. 地震勘探英文专业文章中的经典句子(1)
  11. 域名有www与没有www有什么区别?
  12. 7.性能之巅 洞悉系统、企业与云计算 --- 内存
  13. 浅谈色彩学:以红色为主的色彩配色
  14. ROS创建KDL tree
  15. 计算机编辑学,计算机常识及电文档编辑学习.doc
  16. C++实现DLL注入的完整过程
  17. 学JAVA编程用什么电脑配置_学习编程,你真正需要的是什么样配置的电脑?
  18. 弹指流连间,在梦中轻拾爱的碎片
  19. Java爬虫,信息抓取的实现
  20. ie退出全屏快捷键_讲解win7电脑全屏快捷键介绍

热门文章

  1. MySQL 索引失效的 15 种场景!
  2. MyBatis 的执行流程,学废了!
  3. 骚操作,IDEA防止写代码沉迷插件 !
  4. Redis 持久化——RDB
  5. python 多线程 popen ping指定IP是否在线 判断连通
  6. GO国内镜像加速模块下载
  7. 超松弛迭代法解线性方程组c语言,超松弛迭代法解线性方程组.doc
  8. java appender_log4j的Appenders配置方法
  9. C++PrimerPlus学习——第六章编程练习
  10. android so文件崩溃,android 7.0 因为.so文件而崩溃事件解决