好多网站在发送请求后返回的并不是标准的html页面,而是需要执行一段js后才能获得页面
解决这个问题有多重方法,下面介绍的是使用selenium的方法+PhantomJS的方法。
1.环境
Python 2.7
Ubuntu16.04
2.安装
pip install selenium
sudo apt-get install phantomjs # 使用apt-get 安装的不完整,需要安装下面的包解决,也可以使用其他方法安装
sudo apt-get install nodejs
sudo apt-get install nodejs-legacy
sudo apt-get install npm
sudo npm -g install phantomjs-prebuilt
2.代码
# -*- coding:utf8 -*-
from selenium
import webdriver
from selenium.webdriver.common.desired_capabilities
import DesiredCapabilities
from lxml
import etree
dcap =
dict(DesiredCapabilities.PHANTOMJS)
# 设置浏览器Uesr-Agent
dcap[
"phantomjs.page.settings.userAgent"] = (
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0")
# 设置代理
service_args = [
'--proxy=127.0.0.1:8080',
'--proxy-type=socks5']
# 禁止加载图片可以在一定程度上加快浏览器速度
dcap[
"phantomjs.page.settings.loadImages"] =
False
dv = webdriver.PhantomJS(phantomjs_driver_path,
desired_capabilities=dcap,
service_args=service_args)
dv.get(
"http://blog.csdn.net")
# print dv.page_source.encode('utf-8')
# 可以保存一张网页当前状态的图片
dv.get_screenshot_as_file(
'showcsdn.png')
# 设定最大等待时间
dv.set_page_load_timeout(
40)
# 设置脚本超时时间
dv.set_script_timeout(
10)
# 以下是常用命令
# 获取所有cookie
dv.get_cookies()
# 打印网页源码 ,根据实际情况选择编码方式,有的网站可能是gbk
print dv.page_source.decode(
'utf-8').encode(
'utf-8')
# 可以直接使用xpath在网页源码上进行结构化数据提取
html=etree.HTML(dv.page_source.encode(
'utf-8'))
print html.xpath(
"//a[@class='s-user-name-top']//text()")
# 给指定元素传递参数
dv.find_element_by_xpath(
"input_search"
).send_key(
u
'python'
)
dv.find_element_by_xpath(
"//a[@class='btn-nobg-noborder btn-search']").click()
# dv.find_element_by_id('kw').send_keys(Keys.RETURN)
# 查找某元素,通过class_name
driver.find_element_by_class_name(
'input_search').send_key(
u
'selemium')
# 检查某元素,通过id
driver.find_element_by_id(
'id')
# 打印当前网址
print driver.current_url
# 关闭当前的页面
driver.close()
# 关闭浏览器
driver.quit()
# 隐形等待
dv.implicitly_wait(30)
dv.get_screenshot_as_file(
'show_py.png')
# 解决错误
service_args=['--ignore-ssl-errors=true', '--ssl-protocol=TLSv1']
3.多进程的使用
from multiprocessing import Pool
pool = Pool(8)
data_list = pool.map(get, url_list)
pool.close()
pool.join()
4.找不到元素的问题
有时,phantomJS获得的页面源码的确存在某元素,但通过find_element_by_xpath()
等定位函数却无法获得该元素对象,总是提示“元素不存在”的错误。遇到这种情况,除了检查元素节点路径是否正确外,还应该分析页面源码,检查元素是否被包裹在一个特定的frame中,如果是后者,那么在使用查找函数前,需要额外的处理。
比如网页源码中有如下代码:
<iframe id="topmenuFrame" width="100%" scrolling="no" height="100%" src="topmenu.aspx?>
<div id="haha">text</div>
</iframe>
假如你想要获取id="haha"
的div标签,直接通过driver.find_element_by_id('haha')
就会提示“元素不存在“的错误。
这时需要使用driver.switch_to_frame(driver.find_element_by_id``("topmenuFrame"))
,即先进入id为topmenuFrame的frame,然后再执行driver.find_element_by_id("haha")
,就能正确获得该元素了。
需要注意的是,切换到这个frame之后,只能访问当前frame的内容,如果想要回到默认的内容范围,相当于默认的frame,还需要使用driver.switch_to_default_content()
。
页面中有多个frame时,要注意frame之间的切换。
五.三种等待方式
有些时候点击元素,如果元素还未加载完毕就点击会抛出异常。
这个时候需要等待网页加载完毕再继续执行代码
①强制等待
直接time.sleep(1)
②隐式等待
dv.implicitly_wait(10)
相当于让规定一定的加载时间,时间到了还没有加载完毕就报错
显示等待
相当于每隔一段时间检测一下。