注: 上一篇《Python+Selenium爬取动态加载页面(1)》讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网。数据的获取过程跟人手动获取过程类似,所以也不会对服务器造成更大负荷。本文的代码见Selenium获取动态页面数据2.ipynb或Selenium获取动态页面数据2.py。同样在开始前需要准备环境,具体环境准备参考上一篇

1、数据获取目标

全国水雨情网的数据同样是动态加载出来的,在浏览中打开网页后http://xxfb.hydroinfo.gov.cn/ssIndex.html,可以看到回下图1-1所示的页面。

图1-1 全国水雨情网

可以看到,其中并没有显示任何的数据,如果我们需要查看数据,还需要点击一下其中的几个按钮。比如,我们需要得到其中大型水库的数据,那么需要点击大型水库按钮,得到如下图1-2所示的结果。

图1-2 全国水雨情信息-大型水库

得到这个页面后,就可以从其中的HTML页面源码中解析数据了。

2、详细爬取过程

2.1 打开网页

运行下面代码,会自动弹出Chrome浏览器的窗口;如果用的browser = webdriver.PhantomJS(),则没有窗口出来。浏览器的窗口出来后,可以看到,它加载出我们的页面了。

import re
import pandas as pd
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC # 打开chrome浏览器(需提前安装好chromedriver)
browser = webdriver.Chrome()
# browser = webdriver.PhantomJS()
# 这里经常出现加载超的异常,后面需要处理一下:捕获异常后,刷新浏览器
browser.get("http://xxfb.hydroinfo.gov.cn/ssIndex.html")

2.2 查找目标数据

页面加载完成后,接下需要定位我们的大型水库按钮,通过按浏览器的F12查看源码,可以得到这个按钮的xpath://*[@id="sscontent"]/table/tbody/tr/td/table/tbody/tr[1]/td/table/tbody/tr/td[3]/a,如图2-1所示。

图2-1 xpath定位

定位到按钮后,需要再点击一下。

# 找到大型水库的按钮---通过xpath
btn_water_xpath = "//*[@id=\"sscontent\"]/table/tbody/tr/td/table/tbody/tr[1]/td/table/tbody/tr/td[3]/a"
# 等待响应完成
wait = WebDriverWait(browser, 10)
wait.until(EC.presence_of_element_located((By.XPATH, btn_water_xpath)))
# 查找目标按钮
btn_water = browser.find_element_by_xpath(btn_water_xpath)
# 找到按钮后单击
btn_water.click()

2.2 得到页面源码

数据定位完成后,接下来得到页面源码。按照上面同样的方法,我们需要定位其中的数据表,并等待其加载完成,加载完成后,我们才能读取其页面源码。

# 大型水库的数据表--xpath
water_table_xpath = "//*[@id=\"sktable\"]/table/tbody"
# 得到新的页面,并等待其数据表加载完成
wait = WebDriverWait(browser, 10)
wait.until(EC.presence_of_element_located(
(By.XPATH, water_table_xpath))) soup = BeautifulSoup(browser.page_source, 'lxml')

2.3 提取数据

得到页面源码后,可直接利用Pandas的read_html方法得以其中的表格数据,非常方便。同时我们还需要定位它的表头信息,来得到我们的表头。

# 表头信息
table_head_csel = "#skcontent>table:nth-child(3)>tbody>tr"
table_head = soup.select(table_head_csel)[0] # 通过css选择器,找到水库表信息
table_css_select = "#sktable"
table_content = soup.select(table_css_select)[0] df_table = pd.read_html(str(table_content))[0]
df_table.columns = [h.text for h in table_head.find_all("td")]
# df_table.columns = ['流域', '行政区', '河名', '库名', '库水位(米)', \
# '蓄水量(亿米3)', '入库(米3/秒)', '堤顶高程(米)']

查看提取数据的前5行,如表2.1所示。

表2.1 提取数据前5行
流域 行政区 河名 库名 库水位(米) 蓄水量(亿米3) 入库(米3/秒) 堤顶高程(米)
0 其他流域 新疆 乌伦古河 福海水库 575.14 ↓ 1.756 0 579.00
1 其他流域 新疆 卡浪古尔河 喀浪古尔水库 988.26 — 0.126 1.23 1007.50
2 其他流域 新疆 三屯河 三屯河水库 1024.49 — 0.078 1.982 1039.60
3 其他流域 新疆 头屯河 头屯河水库 986.52 — 0.108 1.75 995.20
4 其他流域 新疆 乌鲁木齐河 红雁池水库 995.54 ↓ 0.234 0 1009.00

2.4 保存数据

数据提取完成后,下面还将其表格的时间提取出来,以作为文件名,防止数据重复。这里利用了一个简单的正则表达式提时间信息,然后利用pandas的to_csv方法,得到两种编码格式的.csv文件。其中rvr_tab_2019_1_22_ch.csv为中文编码格式,可直接用excel打开,如图2-2所示。

# 找到水库信息的时间
table_time_csel = "#skdate"
time_text = soup.select(table_time_csel)[0].text
time_info = re.search(r"(\d{4})年(\d{1,2})月(\d{1,2})", time_text).groups() df_table.to_csv("rvr_tab_%s_%s_%s.csv" % time_info, index=None)
# 换一个编码方式,此文件可以直接用excel打开,不会出现乱码
df_table.to_csv("rvr_tab_%s_%s_%s_ch.csv" % time_info,encoding="GB18030", index=None)

图2-2 获取的数据

总结

本文的方法与上一篇《Python+Selenium爬取动态加载页面(1)》的方法类似,只是多一个按钮点击的过程。

从这两篇博文的数据提取过程来看,简单地,其数据获取有如下图所示的过程。

动态网页数据提取流程

Python+Selenium爬取动态加载页面(2)的更多相关文章

  1. Python+Selenium爬取动态加载页面(1)

    注: 最近有一小任务,需要收集水质和水雨信息,找了两个网站:国家地表水水质自动监测实时数据发布系统和全国水雨情网.由于这两个网站的数据都是动态加载出来的,所以我用了Selenium来完成我的数据获取. ...

  2. Scrapy 框架 使用 selenium 爬取动态加载内容

    使用 selenium 爬取动态加载内容 开启中间件 DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMidd ...

  3. 爬虫再探实战(三)———爬取动态加载页面——selenium

    自学python爬虫也快半年了,在目前看来,我面临着三个待解决的爬虫技术方面的问题:动态加载,多线程并发抓取,模拟登陆.目前正在不断学习相关知识.下面简单写一下用selenium处理动态加载页面相关的 ...

  4. 爬虫再探实战(四)———爬取动态加载页面——请求json

    还是上次的那个网站,就是它.现在尝试用另一种办法——直接请求json文件,来获取要抓取的信息. 第一步,检查元素,看图如下: 过滤出JS文件,并找出包含要抓取信息的js文件,之后就是构造request ...

  5. Python爬虫爬取异步加载的数据

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:努力努力再努力 爬取qq音乐歌手数据接口数据 https://y.qq ...

  6. C#使用phantomjs,爬取AJAX加载完成之后的页面

    1.开发思路:入参根据apiSetting配置文件,分配静态文件存储地址,可实现不同站点的静态页生成功能.静态页生成功能使用无头浏览器生成,生成之后的字符串进行正则替换为固定地址,实现本地正常访问. ...

  7. 转:从pickle看python类成员的动态加载和类的定位

      pickle是Python轻便的对象序列化工具.使用pickle可以方便地把python对象写入文件对象中,或者像soap那样在socket间传送.     按照python的一贯作风,类的成员在 ...

  8. ExtJS 4.1 TabPanel动态加载页面并执行脚本【转】

    ExtJS 4.1 TabPanel动态加载页面并执行脚本 按照官方示例,可以动态加载页面,可是脚本不执行,于是查SDK.google,发现scripts需要设置为true,于是设置该属性,整个代码如 ...

  9. div动态加载页面

    div动态加载页面 /* /// method 1 var url="<%=basePath%>/qne.do?p=pessegerCountSet"; $.post( ...

随机推荐

  1. mysql index hint 在index不存在时的处理

    关于index_hint 在mysql查询语句中可以通过指定index_hint来告诉优化器如何使用索引,详细可以参考这里 index_hint: USE {INDEX|KEY} [FOR {JOIN ...

  2. Oracle 数据库 简单查询

    select DISTINCT dept_id from s_emp; desc s_emp; ; --给入职3年以上员工发10万元年终奖 ; --列出职位是仓库管理员的名字和工资 select la ...

  3. MySQL 8.0.2: Introducing Window Functions

    July 18, 2017MySQL, SQLDag Wanvik MySQL 8.0.2 introduces SQL window functions, or analytic functions ...

  4. 转:.NET面试题汇总(三)

    原文地址:http://www.cnblogs.com/yuan-jun/p/6600692.html 1.简述 private. protected. public. internal 修饰符的访问 ...

  5. 通过yum源在centOS7安装mysql8

    1.去官网下载rpm文件,该文件专门用于yum安装方式: 到官网https://www.mysql.com/downloads/下载社区版Community(针对个人),如下图: 然后拉到最下面,我下 ...

  6. Laravel 执行过程核心

    protected function sendRequestThroughRouter($request){ $this->app->instance('request', $reques ...

  7. openlayer3 基础学习一创建&显示地图

    <!doctype html> <html lang="en"> <head> <link rel="stylesheet&qu ...

  8. CSS布局(三) 布局模型

    布局模型 在网页中,元素有三种布局模型:1.流动模型(Flow) 默认的2.浮动模型 (Float)3.层模型(Layer) 1.流动模型(Flow) 流动(Flow)模型是默认的网页布局模式.也就是 ...

  9. div设置contenteditable="true" 光标消失:原因

    原因1:document.onselectstart= function(){return false;}; 原因2:父层设置了user-select:none 导致 子层设置了 contentedi ...

  10. 设计模式_享元设计模式(flyweight)

    享元模式以共享的方式高效地支持大量的细粒度对象.很多很小的对象,这些对象有很多共同的东西,那就变成一个对象,还有些不同的东西,作为外部的属性,用方法的参数传入 public class Flyweig ...