selenium(自动化测试工具可用于在爬虫中解决js动态加载问题)
简介(本质就是模仿浏览器工作)
Selenium 是什么?一句话,自动化测试工具。它支持各种浏览器,包括 Chrome,Safari,Firefox 等主流界面式浏览器,如果你在这些浏览器里面安装一个 Selenium 的插件,那么便可以方便地实现Web界面的测试。换句话说叫 Selenium 支持这些浏览器驱动。话说回来,PhantomJS(无头浏览器)不也是一个浏览器吗,那么 Selenium 支持不?答案是肯定的,这样二者便可以实现无缝对接了。
然后又有什么好消息呢?Selenium支持多种语言开发,比如 Java,C,Ruby等等,有 Python 吗?那是必须的!
安装一下 Python 的 Selenium 库,再安装好 PhantomJS,不就可以实现 Python+Selenium+PhantomJS 的无缝对接了嘛!PhantomJS 用来渲染解析JS,Selenium 用来驱动以及与 Python 的对接,Python 进行后期的处理,完美的三剑客!
有人问,为什么不直接用浏览器而用一个没界面的 PhantomJS(无头浏览器) 呢?答案是:效率高!而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器。
前面爬取站长素材的时候图片是必须有浏览器视窗才加载。用selenium可以解决这种视窗加载问题。
环境安装
1、下载安装selenium
pip3 install selenium
2、下载浏览器对应版本的驱动(这里最好用谷歌浏览器方便强大)
http://chromedriver.storage.googleapis.com/index.html
selenium演示:
from selenium import webdriver import time #指定浏览器,参数是浏览器驱动的路径,前面加上r防止转义 driver = webdriver.Chrome(r"./chromedriver.exe")#打开浏览器 #用get打开页面 driver.get("https://www.baidu.com") # 下面是演示一下其他操作 # #查找页面的“设置”选项,并点击 # driver.find_elements_by_link_text('设置')[0].click() # time.sleep(1) # #打开搜索设置选项 # driver.find_elements_by_link_text('搜索设置')[0].click() # time.sleep(1) # # 选中每页显示50条 下拉不能先点击 直接先选中找到子元素点击 # m = driver.find_element_by_id("nr") # time.sleep(2) # m.find_element_by_xpath('//*[@id="nr"]/option[3]').click() # time.sleep(0.7) # #类名可能多个 会返回列表 因此取第一个 id,xpath都是唯一的 # driver.find_elements_by_class_name("prefpanelgo")[0].click() # time.sleep(1) # #处理弹出的警告页面 确认accept() 取消dismiss() # driver.switch_to_alert().accept() #找到搜索框 输入关键字(.send_keys) driver.find_element_by_id('kw').send_keys("校花") time.sleep(0.5) #找到搜索按钮 提交 driver.find_element_by_id("su").click() time.sleep(2) #找到图片搜索栏链接 看图片 driver.find_elements_by_link_text("图片")[0].click() time.sleep(3) #退出浏览器 关闭浏览器 driver.quit()
selenium爬取雪球 投资的网站首页(涉及到js动态加载)
from selenium import webdriver from lxml import etree import time driver = webdriver.Chrome("./chromedriver.exe") #让浏览器指定url发起请求 经测试它有动态加载数据 driver.get("https://xueqiu.com/") time.sleep(3) #获取浏览器打开的当前页面的源码数据******* page_text = driver.page_source #用etree解析数据 tree = etree.HTML(page_text) text = tree.xpath('//*[@id="app"]/div[3]/div[1]/div[2]/div[2]/div[1]/div[3]/p/text()')[0] print(text) time.sleep(2) driver.quit() ###打印结果: """好买商学院专注出品原创内容,内容包括金融理财知识,基金基础知识,股票,债券,大家想了解更多, 就点击头像关注好买商学院吧,更多精彩内容等你来看喔! 股市简介: 周五(9.27), 今日早盘两市微幅高开后分化,沪指横盘震荡,深成指、创业板指双双走高涨超1%。截止收盘,沪指涨0.11%,报收293..."""
selenium相关行为动作的制定:
from selenium import webdriver import time driver = webdriver.Chrome("./chromedriver.exe") #打开淘宝网站 driver.get("https://www.taobao.com") time.sleep(2) #定位到想要找的节点输入框 input_text = driver.find_element_by_id("q") #输入你想输入的关键字send_keys() input_text.send_keys("华为") time.sleep(3) #类选择器 找到节点按钮 btn = driver.find_element_by_css_selector(".btn-search") #点击按钮发送 btn.click() time.sleep(2) #执行js程序(js注入) driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") time.sleep(2) driver.quit()
运行有点久,时间可以自行调节。
动作链:
from selenium import webdriver import time #导入动作链模块 from selenium.webdriver import ActionChains driver = webdriver.Chrome("./chromedriver.exe") #这个菜鸟教程里面有iframe标签以内的html标签 driver.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable") #如果定位节点在标签iframe内,那么则必须使用switch_to进行iframe的切换 driver.switch_to.frame("iframeResult") #开始定位节点(选中节点) sm_div = driver.find_element_by_id("draggable") #实例化一个动作链对象(将浏览器对象作为参数传入) action = ActionChains(driver) #点击并且长按(节点对象) action.click_and_hold(sm_div) #开始模拟人拖动 for i in range(5): #让sm+div移动 action.move_by_offset(17,0).perform()#一定要加perform(立即执行动作链)不然不会移动 容易忘记他***************** time.sleep(0.6) time.sleep(3) #退出浏览器 driver.quit()
无头浏览器(PhantomJS停止更新了,因此用谷歌的无头浏览器):
from selenium import webdriver from lxml import etree import time #无头浏览器设置(*********增加爬取效率) from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') #无头浏览器需要传入参数在实例化的浏览器对象中***** driver = webdriver.Chrome(executable_path="./chromedriver.exe",options=chrome_options) #让浏览器指定url发起请求 经测试它有动态加载数据 driver.get("https://xueqiu.com/") time.sleep(3) #获取浏览器打开的当前页面的源码数据******* page_text = driver.page_source #用etree解析数据 tree = etree.HTML(page_text) text = tree.xpath('//*[@id="app"]/div[3]/div[1]/div[2]/div[2]/div[1]/div[3]/p/text()')[0] print(text) time.sleep(2) driver.quit()
规避被监测(用于反反爬措施):
from selenium import webdriver from lxml import etree import time #*****************规避被监测*********************** from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) #无头浏览器设置(*********增加爬取效率) from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') #无头浏览器需要传入参数在实例化的浏览器对象中 driver = webdriver.Chrome(executable_path="./chromedriver.exe",options=option,chrome_options=chrome_options) #让浏览器指定url发起请求 经测试它有动态加载数据 driver.get("https://xueqiu.com/") time.sleep(3) #获取浏览器打开的当前页面的源码数据******* page_text = driver.page_source #用etree解析数据 tree = etree.HTML(page_text) text = tree.xpath('//*[@id="app"]/div[3]/div[1]/div[2]/div[2]/div[1]/div[3]/p/text()')[0] print(text) time.sleep(2) driver.quit()
模拟qq空间登录:
from selenium import webdriver from lxml import etree import time driver = webdriver.Chrome(executable_path='./chromedriver.exe') driver.get('https://qzone.qq.com/') # 在web 应用中经常会遇到frame 嵌套页面的应用,使用WebDriver # 每次只能在一个页面上识别元素,对于frame 嵌套内的页面上的元素, # 直接定位是定位是定位不到的。这个时候就需要通过switch_to.frame()方法将当前定位的主体切换了frame 里。 driver.switch_to.frame('login_frame') driver.find_element_by_id('switcher_plogin').click() time.sleep(3) #如果有别人的qq号 先清除 driver.find_element_by_id('u').clear() # 这里填写你的QQ号 driver.find_element_by_id('u').send_keys('1259553287') time.sleep(3) #如果有别人的密码 driver.find_element_by_id('p').clear() time.sleep(4) driver.find_element_by_id('p').send_keys('xxxxxxxxx') # 这里填写你的QQ密码 time.sleep(3) driver.find_element_by_id('login_button').click() time.sleep(5) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) # page_text = driver.page_source # # tree = etree.HTML(page_text) # # 执行解析操作 # li_list = tree.xpath('//ul[@id="feed_friend_list"]/li') # for li in li_list: # text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()') # text = ''.join(text_list) # print(text + '\n\n\n') driver.close()
执行JavaScript
对于某些操作,Selenium API并没有提供。比如,下拉进度条,它可以直接模拟运行JavaScript,此时使用execute_script()
方法即可实现,代码如下: