####selenium + phantomjs
+ Selenium
Selenium可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。Selenium自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们大多数时候需要让它内嵌在代码中运行,所以我们可以用一个叫PhantomJS的工具代替真实的浏览器(或者使用chromedriver等)。
pip install selenium 安装, pip show selenium 查看是否安装成功。
Selenium库里有个叫WebDriver的API。WebDriver有点儿像可以加载网站的浏览器,但是它可以像BeautifulSoup或者其他Selector对象一样用来查找页面元素,与页面上的元素进行交互(发送文本、点击等),以及执行其他动作来运行网络爬虫。
+ Splinter
使用Python开发的开源Web应用测试工具,它可以帮你实现自动浏览站点和与其进行交互,类似selenium。
+ Phantomjs
PhantomJS是一个基于Webkit的“无界面”(headless)浏览器,它会把网站加载到内存并执行页面上的JavaScript,因为不会展示图形界面,所以运行起来比完整的浏览器要高效。
如果我们把Selenium和PhantomJS结合在一起,就可以运行一个非常强大的网络爬虫了,这个爬虫可以处理JavaScript、Cookie、headers,以及任何我们真实用户需要做的事情。
下载链接:http://npm.taobao.org/dist/phantomjs/
+ 开发环境
selenium 3.4.3 + phantomjs 2.1.1
+phantomjs常用配置
from selenium import webdriver
# 引入配置对象DesiredCapabilities
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
dcap = dict(DesiredCapabilities.PHANTOMJS)
#从USER_AGENTS列表中随机选一个浏览器头,伪装浏览器
dcap["phantomjs.page.settings.userAgent"] = (random.choice(USER_AGENTS))
# 不载入图片,爬页面速度会快很多
dcap["phantomjs.page.settings.loadImages"] = False
# 设置代理
service_args = ['--proxy=127.0.0.1:9999','--proxy-type=socks5']
#打开带配置信息的phantomJS浏览器
driver = webdriver.PhantomJS(phantomjs_driver_path, desired_capabilities=dcap,service_args=service_args)
# 隐式等待5秒,可以自己调节
driver.implicitly_wait(5)
# 设置10秒页面超时返回,类似于requests.get()的timeout选项,driver.get()没有timeout选项
# 以前遇到过driver.get(url)一直不返回,但也不报错的问题,这时程序会卡住,设置超时选项能解决这个问题。
driver.set_page_load_timeout(10)
# 设置10秒脚本超时时间
driver.set_script_timeout(10)
+ webdriver基本操作
与页面交互:
element = driver.find_element_by_id()
element = driver.find_element_by_name()
element = driver.find_element_by_xpath()
element = find_element_by_class_name()
element = find_element_by_tag_name()
element = find_element_by_link_text()
element = find_element_by_partial_link_text()
element = find_element_by_css_selector()
element.send_keys("some text")
element.clear()
填写表格:
WebDriver的支持类包括一个叫做 ``Select``的类,他提供有用的方法处理这些内容:
from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_name('name'))
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)
WebDriver 也提供一些有用的方法来取消选择已经选择的元素:
select = Select(driver.find_element_by_id('id'))
select.deselect_all()
element.submit()
拖放:
element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")
from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element, target).perform()
在不同的窗口和框架之间移动:
driver.switch_to_window("windowName")
driver.switch_to_frame("frameName")
弹出对话框处理:
alert = driver.switch_to_alert()
使用此对象,您现在可以接受、排除、读取其内容, 甚至可以在prompt对话框中输入
访问浏览器记录;
driver.forward()
driver.back()
操作Cookies:
get_cookie(): 获得所有cookie信息。
get_cookie(name):返回字典的key为name的cookie
add_cookie(cookie_dict):添加cookie。“cookie_dict”指字典对象,必须有name和value值。
delete_cookie(name,optionsString):删除cookie信息。“name”是要删除的cookie的名称。“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域”
delete_all_cookies():删除所有cookie信息。
等待页面加载完成:
现在的大多数的Web应用程序是使用Ajax技术。当一个页面被加载到浏览器时, 该页面内的元素可以在不同的时间点被加载。这使得定位元素变得困难, 如果元素不再页面之中,会抛出ElementNotVisibleException 异常。 使用 waits, 我们可以解决这个问题。waits提供了一些操作之间的时间间隔 - 主要是定位元素或针对该元素的任何其他操作。
显式等待是你在代码中定义等待一定条件发生后再进一步执行你的代码。 最糟糕的案例是使用time.sleep(),它将条件设置为等待一个确切的时间段。 这里有一些方便的方法让你只等待需要的时间。WebDriverWait结合ExpectedCondition 是实现的一种方式。class WebDriverWait(object):driver, timeout, poll_frequency。
如果某些元素不是立即可用的,隐式等待是告诉WebDriver去等待一定的时间后去查找元素。 默认等待时间是0秒,一旦设置该值,隐式等待是设置该WebDriver的实例的生命周期。
参考链接:https://blog.csdn.net/wycaoxin3/article/details/74017971
+ 网页基本操作示例
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
execute_path = r'D:\phantomjs\bin\phantomjs.exe'
url = 'http://www.baidu.com/'
driver = webdriver.PhantomJS(executable_path=execute_path)
driver.get(url)
print(driver.title)
#data = driver.find_element_by_id('wrapper').text
#print(data)
driver.find_element_by_id('kw').send_keys('美女')
driver.find_element_by_id('su').click()
time.sleep(2)
driver.save_screenshot('meinv.jpg')
print(driver.get_cookies())
+ phantomjs + selenium登录csdn
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
url = 'http://jandan.net/ooxx'
executable_path=r'D:\phantomjs\bin\phantomjs.exe'
dcap = dict(DesiredCapabilities.PHANTOMJS)
dcap["phantomjs.page.settings.userAgent"] = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.68"
service_args = ['--ignore-ssl-errors=true','--ssl-protocol=TLSv1'] #返回Screenshot: available via screen错误解决方法
driver = webdriver.PhantomJS(executable_path=executable_path,desired_capabilities=dcap,service_args=service_args)
driver.set_page_load_timeout(10)
driver.set_script_timeout(10)
driver.get(url)
#sleep(9)
print(driver.page_source)
+ 模拟登陆路由器返回设备列表
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from bs4 import BeautifulSoup
url = 'http://192.168.2.1/login.asp'
executable_path=r'D:\phantomjs\bin\phantomjs.exe'
dcap = dict(DesiredCapabilities.PHANTOMJS)
dcap["phantomjs.page.settings.userAgent"] = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.68"
service_args = ['--ignore-ssl-errors=true','--ssl-protocol=TLSv1'] #返回Screenshot: available via screen错误解决方法
driver = webdriver.PhantomJS(executable_path=executable_path,desired_capabilities=dcap,service_args=service_args)
driver.set_page_load_timeout(10)
driver.set_script_timeout(10)
driver.get(url)
driver.find_element_by_name('password').send_keys('xxx')
sleep(1)
driver.find_element_by_name('login').click()
sleep(3)
driver.find_element_by_id('list22').click()
sleep(3)
bsObj = BeautifulSoup(driver.page_source)
#print(bsObj.prettify())
table = bsObj.find('table',{'id':'online_table'})
thead = table.find('thead')
td_thead = thead.find_all('td')
for td in td_thead:
print(td.get_text(),end=' ')
tbody = table.find('tbody')
tr = tbody.find_all('tr')
for i_tr in tr:
td = i_tr.find_all('td')
for i_td in td:
print(i_td.get_text(),end=' ')
print('\n')
#for sibling in bsObj.find('table',{'id':'online_table'}).descentants:
# print(sibling)
#print(driver.page_source)
####selenium + chromedriver
(1)selenium.common.exceptions.NoSuchElementException: Message: '{"errorMessage":"Unable to find element with name
定位元素仅会在当前所处的frame中寻找该元素,如果有多个frame时需要先切换到对应的frame下才能够找到该元素。重新查看需要定位的页面信息发现果真要寻找的元素在一个iframe下,需调用driver.switch_to_frame切换至该iframe下才能定位。
(2)driver.page_source可以查看当前的页面内容
(3)Selenium打开谷歌浏览器提示chromedriver.exe停止运行且浏览器显示请关闭开发者模式,提示关闭开发者模式,其实是chromedriver.exe与chrome 浏览器版本不一致导致的,下载完chromedriver之后可以手动运行查看它的真实版本,官网下载的版本与实际版本号不对应,可以到阿里的镜像源里下载。
(4)用phantomjs switch_to_frame加载页面失败,但是chromedriver是成功的,目前还没找到原因。
(5)最新的selenium已不再支持phantomjs,亲测版本3.4.3是支持的。
+ selenium + chromedriver 登录126邮箱
from selenium import webdriver
from time import sleep
driver=webdriver.Chrome()
driver.get("https://mail.126.com/")
sleep(2)
#frame/iframe 表单嵌套
#xpath=driver.find_element_by_id("x-URS-iframe")
driver.switch_to_frame('x-URS-iframe')
# 也可以用这句,作用一样 driver.switch_to_frame(xpath)
sleep(2)
driver.find_element_by_name("email").clear()
driver.find_element_by_name("email").send_keys("xxx")
sleep(2)
driver.find_element_by_name("password").clear()
driver.find_element_by_name("password").send_keys("yyy")
sleep(2)
driver.find_element_by_id("dologin").click()
sleep(2)
driver.find_element_by_link_text('登录').click()
#driver.quit()
+ chromedriver路由登录返回设备列表
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from bs4 import BeautifulSoup
url = 'http://192.168.2.1/login.asp'
'''executable_path=r'D:\phantomjs\bin\phantomjs.exe'
dcap = dict(DesiredCapabilities.PHANTOMJS)
dcap["phantomjs.page.settings.userAgent"] = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.68"
service_args = ['--ignore-ssl-errors=true','--ssl-protocol=TLSv1'] #返回Screenshot: available via screen错误解决方法
'''
driver = webdriver.Chrome()
#driver.set_page_load_timeout(10)
#driver.set_script_timeout(10)
driver.get(url)
driver.find_element_by_name('password').send_keys('xxx')
sleep(1)
driver.find_element_by_name('login').click()
sleep(3)
driver.find_element_by_id('list22').click()
sleep(3)
bsObj = BeautifulSoup(driver.page_source)
#print(bsObj.prettify())
table = bsObj.find('table',{'id':'online_table'})
thead = table.find('thead')
td_thead = thead.find_all('td')
for td in td_thead:
print(td.get_text(),end=' ')
tbody = table.find('tbody')
tr = tbody.find_all('tr')
for i_tr in tr:
td = i_tr.find_all('td')
for i_td in td:
print(i_td.get_text(),end=' ')
print('\n')
driver.quit()
#####phantomjs vs chromedriver
(1)selenium3.x不再支持phantomjs,所以后续用chromedriver比较好;
(2)phantomjs无需打开浏览器加载,速度快,占用内存小;
(3)phantomjs加载时间不确定,经常会出现“Screenshot: available via screen”错误,chromedriver不会出现此错误;
(4)两者的程序一样,只需要在初始化webdriver的地方小小修改一下,就可以两者都适用,差别在与有头和无头;
(5)在速度没有要求的前提下优先适用chromedriver。