Python+Selenium爬取动态加载页面(2)
注: 上一篇《Python+Selenium爬取动态加载页面(1)》讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网。数据的获取过程跟人手动获取过程类似,所以也不会对服务器造成更大负荷。本文的代码见Selenium获取动态页面数据2.ipynb或Selenium获取动态页面数据2.py。同样在开始前需要准备环境,具体环境准备参考上一篇。
1、数据获取目标
全国水雨情网的数据同样是动态加载出来的,在浏览中打开网页后http://xxfb.hydroinfo.gov.cn/ssIndex.html,可以看到回下图1-1所示的页面。
可以看到,其中并没有显示任何的数据,如果我们需要查看数据,还需要点击一下其中的几个按钮。比如,我们需要得到其中大型水库的数据,那么需要点击大型水库
按钮,得到如下图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所示。
定位到按钮后,需要再点击一下。
# 找到大型水库的按钮---通过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所示。
流域 | 行政区 | 河名 | 库名 | 库水位(米) | 蓄水量(亿米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)
总结
本文的方法与上一篇《Python+Selenium爬取动态加载页面(1)》的方法类似,只是多一个按钮点击的过程。
从这两篇博文的数据提取过程来看,简单地,其数据获取有如下图所示的过程。
Python+Selenium爬取动态加载页面(2)的更多相关文章
- Python+Selenium爬取动态加载页面(1)
注: 最近有一小任务,需要收集水质和水雨信息,找了两个网站:国家地表水水质自动监测实时数据发布系统和全国水雨情网.由于这两个网站的数据都是动态加载出来的,所以我用了Selenium来完成我的数据获取. ...
- Scrapy 框架 使用 selenium 爬取动态加载内容
使用 selenium 爬取动态加载内容 开启中间件 DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMidd ...
- 爬虫再探实战(三)———爬取动态加载页面——selenium
自学python爬虫也快半年了,在目前看来,我面临着三个待解决的爬虫技术方面的问题:动态加载,多线程并发抓取,模拟登陆.目前正在不断学习相关知识.下面简单写一下用selenium处理动态加载页面相关的 ...
- 爬虫再探实战(四)———爬取动态加载页面——请求json
还是上次的那个网站,就是它.现在尝试用另一种办法——直接请求json文件,来获取要抓取的信息. 第一步,检查元素,看图如下: 过滤出JS文件,并找出包含要抓取信息的js文件,之后就是构造request ...
- Python爬虫爬取异步加载的数据
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:努力努力再努力 爬取qq音乐歌手数据接口数据 https://y.qq ...
- C#使用phantomjs,爬取AJAX加载完成之后的页面
1.开发思路:入参根据apiSetting配置文件,分配静态文件存储地址,可实现不同站点的静态页生成功能.静态页生成功能使用无头浏览器生成,生成之后的字符串进行正则替换为固定地址,实现本地正常访问. ...
- 转:从pickle看python类成员的动态加载和类的定位
pickle是Python轻便的对象序列化工具.使用pickle可以方便地把python对象写入文件对象中,或者像soap那样在socket间传送. 按照python的一贯作风,类的成员在 ...
- ExtJS 4.1 TabPanel动态加载页面并执行脚本【转】
ExtJS 4.1 TabPanel动态加载页面并执行脚本 按照官方示例,可以动态加载页面,可是脚本不执行,于是查SDK.google,发现scripts需要设置为true,于是设置该属性,整个代码如 ...
- div动态加载页面
div动态加载页面 /* /// method 1 var url="<%=basePath%>/qne.do?p=pessegerCountSet"; $.post( ...
随机推荐
- mysql index hint 在index不存在时的处理
关于index_hint 在mysql查询语句中可以通过指定index_hint来告诉优化器如何使用索引,详细可以参考这里 index_hint: USE {INDEX|KEY} [FOR {JOIN ...
- Oracle 数据库 简单查询
select DISTINCT dept_id from s_emp; desc s_emp; ; --给入职3年以上员工发10万元年终奖 ; --列出职位是仓库管理员的名字和工资 select la ...
- MySQL 8.0.2: Introducing Window Functions
July 18, 2017MySQL, SQLDag Wanvik MySQL 8.0.2 introduces SQL window functions, or analytic functions ...
- 转:.NET面试题汇总(三)
原文地址:http://www.cnblogs.com/yuan-jun/p/6600692.html 1.简述 private. protected. public. internal 修饰符的访问 ...
- 通过yum源在centOS7安装mysql8
1.去官网下载rpm文件,该文件专门用于yum安装方式: 到官网https://www.mysql.com/downloads/下载社区版Community(针对个人),如下图: 然后拉到最下面,我下 ...
- Laravel 执行过程核心
protected function sendRequestThroughRouter($request){ $this->app->instance('request', $reques ...
- openlayer3 基础学习一创建&显示地图
<!doctype html> <html lang="en"> <head> <link rel="stylesheet&qu ...
- CSS布局(三) 布局模型
布局模型 在网页中,元素有三种布局模型:1.流动模型(Flow) 默认的2.浮动模型 (Float)3.层模型(Layer) 1.流动模型(Flow) 流动(Flow)模型是默认的网页布局模式.也就是 ...
- div设置contenteditable="true" 光标消失:原因
原因1:document.onselectstart= function(){return false;}; 原因2:父层设置了user-select:none 导致 子层设置了 contentedi ...
- 设计模式_享元设计模式(flyweight)
享元模式以共享的方式高效地支持大量的细粒度对象.很多很小的对象,这些对象有很多共同的东西,那就变成一个对象,还有些不同的东西,作为外部的属性,用方法的参数传入 public class Flyweig ...