excel抓取网页动态数据(使用Selenium抓取JavaScript动态生成数据的网页Python(组图) )
优采云 发布时间: 2021-10-26 21:06excel抓取网页动态数据(使用Selenium抓取JavaScript动态生成数据的网页Python(组图)
)
小猪的 Python 学习之旅-5. 使用 Selenium 从 JavaScript 动态生成数据抓取网页
Python
介绍
自从学了爬虫,每天不写个爬虫*敏*感*词*姐就觉得不爽:
*敏*感*词*姐长得还不错,就是身体越来越瘦了,多喝点营养快递吧!
(快来学Python爬虫,一起爬爬可爱的*敏*感*词*姐~)
抓的太多了,发现有些小网站很狡猾,开始反爬虫,不是直接。
生成数据,但是通过加载JS生成数据,然后你打开Chrome浏览器
开发者选项,然后你会发现 Elements 页面结构和 Network capture packet capture
返回的内容其实是不一样的,网络抓包里没有对应的数据。
本来应该放数据的地方,竟然是JS代码,比如煎蛋妹妹的图片:
对于我这种不懂JS的安卓狗,不禁感叹:
抓不到数据怎么破?一开始想着自己学一波JS基础语法,然后尝试模拟抓包。
拿到别人的js文件,自己分析一下逻辑,然后摆弄真实的URL,然后
还是放弃了,有的js被加密了,要爬的页面太多了,
什么时候分析每个这样的分析...
我偶然发现有一个自动化测试框架:Selenium 可以帮助我们处理这个问题。
简单说说这个东西的使用,我们可以写代码让浏览器:
那么这个东西不支持浏览器功能,需要联系第三方浏览器
配合使用支持以下浏览器,需要下载相应的浏览器驱动
在对应的Python路径下:
铬合金:
火狐:
幻影JS:
IE:
边缘:
歌剧:
下面直接开始本节的内容吧~
1.安装硒
这个很简单,直接通过pip命令行安装:
sudo pip install selenium
PS:记得公司小伙伴问我为什么在win上不能执行pip,我下载了很多pip。
其实安装Python3的话,默认已经自带pip了,需要单独配置环境
变量,pip的路径在Python安装目录的Scripts目录下~
在Path后面加上这个路径就行了~
2.下载浏览器驱动
因为Selenium没有浏览器,需要依赖第三方浏览器,调用第三方
如果你用的是新浏览器,需要下载浏览器的驱动,因为我用的是Chrome,所以我会用
我们以 Chrome 为例。其他浏览器可以自行搜索相关信息!打开 Chrome 浏览器并输入:
chrome://version
可以查看Chrome浏览器版本的相关信息,这里主要是注意版本号:
61.好的,那么到下面网站查看对应的驱动版本号:
好的,接下来下载v2.34版本的浏览器驱动:
下载完成后,解压zip文件,将解压后的chromedriver.exe复制到Python中
脚本目录。(这里不用担心win32,64位浏览器可以正常使用!)
PS:对于Mac,将解压后的文件复制到usr/local/bin目录下
对于Ubuntu,复制到:usr/bin目录
接下来我们写一个简单的代码来测试一下:
from selenium import webdriverbrowser = webdriver.Chrome() # 调用本地的Chrome浏览器browser.get('http://www.baidu.com') # 请求页面,会打开一个浏览器窗口html_text = browser.page_source # 获得页面代码browser.quit() # 关闭浏览器print(html_text)
执行这段代码会自动调出浏览器访问百度:
并且控制台会输出HTML代码,也就是直接获取到的Elements页面结构,
JS执行后的页面~接下来就可以抢到我们的煎蛋少女图了~
3.Selenium 简单实战:抢煎蛋少女图
直接分析Elements页面的结构,找到你想要的关键节点:
明明这是我们抓到的*敏*感*词*姐的照片,复制这个网址看看我们打印出来的
页面结构有没有这个东西:
是的这很好。有了这个页面数据,让我们通过一波美汤来搞定我们
你要的资料~
经过上面的过滤,我们就可以得到我们妹图的URL:
只需打开一个验证,啧:
看到下一页只有30个*敏*感*词*姐,显然满足不了我们。我们第一次加载它。
当你第一次得到一波页码的时候,然后你就知道有多少页了,然后你就可以拼接URL并自己加载了
不同的页面,比如这里总共有448个页面:
可以拼接成这样的网址:
获取过滤下的页码:
接下来,我将填写代码,循环抓取每个页面上的*敏*感*词*姐,并将其下载到本地。
完整代码如下:
import osfrom selenium import webdriverfrom bs4 import BeautifulSoupimport urllib.requestimport sslimport urllib.errorbase_url = 'http://jandan.net/ooxx'pic_save_path = "output/Picture/JianDan/"# 下载图片def download_pic(url): correct_url = url if url.startswith('//'): correct_url = url[2:] if not url.startswith('http'): correct_url = 'http://' + correct_url print(correct_url) headers = { 'Host': 'wx2.sinaimg.cn', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/61.0.3163.100 Safari/537.36 ' } try: req = urllib.request.Request(correct_url, headers=headers) resp = urllib.request.urlopen(req) pic = resp.read() pic_name = correct_url.split("/")[-1] with open(pic_save_path + pic_name, "wb+") as f: f.write(pic) except (OSError, urllib.error.HTTPError, urllib.error.URLError, Exception) as reason: print(str(reason))# 打开浏览器模拟请求def browser_get(): browser = webdriver.Chrome() browser.get('http://jandan.net/ooxx') html_text = browser.page_source page_count = get_page_count(html_text) # 循环拼接URL访问 for page in range(page_count, 0, -1): page_url = base_url + '/' + str(page) print('解析:' + page_url) browser.get(page_url) html = browser.page_source get_meizi_url(html) browser.quit()# 获取总页码def get_page_count(html): soup = BeautifulSoup(html, 'html.parser') page_count = soup.find('span', attrs={'class': 'current-comment-page'}) return int(page_count.get_text()[1:-1]) - 1# 获取每个页面的*敏*感*词*姐def get_meizi_url(html): soup = BeautifulSoup(html, 'html.parser') ol = soup.find('ol', attrs={'class': 'commentlist'}) href = ol.findAll('a', attrs={'class': 'view_img_link'}) for a in href: download_pic(a['href'])if __name__ == '__main__': ssl._create_default_https_context = ssl._create_unverified_context if not os.path.exists(pic_save_path): os.makedirs(pic_save_path) browser_get()
操作结果:
看看我们的输出文件夹~
是的,发了这么多*敏*感*词*姐,就是想骗你学Python!
4.PhantomJS
PhantomJS 没有界面浏览器,特点:会将网站加载到内存中并执行
JavaScript,因为它不显示图形界面,所以它比完整的浏览器运行效率更高。
(如果某些Linux主机上没有图形界面,有界面的浏览器是不能使用的。
这个问题可以通过 PhantomJS 来规避)。
在 Win 上安装 PhantomJS:
在 Ubuntu/MAC 上安装 PhantomJS:
sudo apt-get install phantomjs
!!!关于 PhantomJS 的重要说明:
今年 4 月,Phantom.js 的维护者宣布退出 PhantomJS。
这意味着该项目可能不再维护!!!Chrome 和 FireFox 也开始了
提供Headless模式(不需要挂浏览器),所以估计用PhantomJS的小伙伴
会慢慢迁移到这两个浏览器。Windows Chrome 需要 60 以上的版本才能支持
Headless 模式,启用 Headless 模式也很简单:
selenium 的官方文档中还写道:
运行时也会报这个警告:
5.Selenium实战:模拟登录CSDN并保存Cookie
CSDN登录网站:
分析页面结构,不难发现对应的登录输入框和登录按钮:
我们要做的就是在这两个节点输入账号密码,然后触发登录按钮,
同时在本地保存Cookie,然后就可以带着Cookie访问相关页面了~
首先写一个方法来模拟登录:
找到输入账号密码的节点,设置你的账号密码,然后找到login
按钮节点,点击一次,然后等待登录成功,登录成功后可以对比
current_url 是否已更改。然后在这里保存 Cookies
我用的是pickle库,你可以用其他的,比如json,或者字符串拼接,
然后保存到本地。如果没有意外,应该可以拿到Cookie,然后使用
Cookie 访问主页。
通过add_cookies方法设置Cookie,参数为字典类型,必须先
访问get链接一次,然后设置cookie,否则会报无法设置cookie的错误!
通过查看右下角是否变为登录状态就可以知道是否使用Cookie登录成功:
6.Selenium 常用函数
Seleninum 作为自动化测试的工具,自然提供了很多自动化操作的功能。
下面是我觉得比较常用的功能,更多的可以看官方文档:
官方API文档:
1) 定位元素
PS:将元素更改为元素将定位所有符合条件的元素并返回一个列表
例如:find_elements_by_class_name
2) 鼠标操作
有时需要在页面上模拟鼠标操作,例如:单击、双击、右键单击、按住、拖动等。
您可以导入 ActionChains 类:mon.action_chains.ActionChains
使用 ActionChains(driver).XXX 调用对应节点的行为
3) 弹窗
对应类:mon.alert.Alert,感觉用的不多...
如果触发到一定时间,弹出对话框,可以调用如下方法获取对话框:
alert = driver.switch_to_alert(),然后可以调用以下方法:
4)页面前进、后退、切换
切换窗口:driver.switch_to.window("窗口名称")
或者通过window_handles来遍历
用于 driver.window_handles 中的句柄:
driver.switch_to_window(句柄)
driver.forward()#forward
driver.back()# 返回
5) 页面截图
driver.save_screenshot("Screenshot.png")
6) 页面等待
现在越来越多的网页使用Ajax技术,所以程序无法判断一个元素什么时候完全
加载完毕。如果实际页面等待时间过长,某个dom元素还没有出来,但是你的
代码直接使用这个WebElement,会抛出NullPointer异常。
为了避免元素定位困难,增加ElementNotVisibleException的概率。
所以Selenium提供了两种等待方式,一种是隐式等待,一种是显式等待。
显式等待:
显式等待指定某个条件,然后设置最大等待时间。如果不是这个时候
如果找到该元素,则会抛出异常。
from selenium import webdriverfrom selenium.webdriver.common.by import By# WebDriverWait 库,负责循环等待from selenium.webdriver.support.ui import WebDriverWait# expected_conditions 类,负责条件出发from selenium.webdriver.support import expected_conditions as ECdriver = webdriver.PhantomJS()driver.get("http://www.xxxxx.com/loading")try: # 每隔10秒查找页面元素 id="myDynamicElement",直到出现则返回 element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "myDynamicElement")) )finally: driver.quit()
如果不写参数,程序会调用0.5s一次,检查元素是否默认已经生成。
如果原创元素存在,它将立即返回。
下面是一些内置的等待条件,你可以直接调用这些条件,而不是自己调用
写一些等待条件。
标题_是
标题_收录
Presence_of_element_located
visibility_of_element_located
可见性_of
Presence_of_all_elements_located
text_to_be_present_in_element
text_to_be_present_in_element_value
frame_to_be_available_and_switch_to_it
invisibility_of_element_located
element_to_be_clickable – 显示并启用。
staleness_of
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
alert_is_present
隐式等待:
隐式等待比较简单,就是简单的设置一个等待时间,以秒为单位。
from selenium import webdriverdriver = webdriver.PhantomJS()driver.implicitly_wait(10) # secondsdriver.get("http://www.xxxxx.com/loading")myDynamicElement = driver.find_element_by_id("myDynamicElement")
当然,如果不设置,则默认等待时间为0。
7.执行JS语句
driver.execute_script(js 语句)
例如,滚动到底部:
js = document.body.scrollTop=10000
driver.execute_script(js)
概括
本节讲解一波使用Selenium自动化测试框架抓取JavaScript动态生成的数据,
Selenium 需要依赖第三方浏览器,注意过时的 PhantomJS 无界面浏览器
对于问题,可以使用Chrome和FireFox提供的HeadLess来替换;通过抓住煎蛋女孩
模拟CSDN自动登录的图片和例子,熟悉Selenium的基本使用,或者收很多货。
当然Selenium的水还是很深的,目前我们可以用它来应对JS动态加载数据页面
数据采集就够了。
最近天气有点冷,大家记得及时添衣哦~
另外,因为这周的事情比较多,先破了。下周见。下一块要啃的骨头是
Python是多线程的,视觉上可以啃几个部分,敬请期待~
顺便写下你的想法:
下载本节源码:
本节参考资料:
来吧,Py 交易
如果想加群一起学Py,可以加智障机器人小猪,验证信息收录:
python,python,py,py,添加组,事务,关键词之一即可;
验证通过后回复群获取群链接(不要破解机器人!!!)~~~
欢迎像我一样的Py初学者,Py大神加入,愉快交流学习♂学习,van♂转py。