参考:Python3网络爬虫开发实战
问题:Ajax 是javascript动态渲染页面的一种情形,可以通过分析Ajax,然后借用requests和urllib来实现数据爬取。不过Javascript动态渲染的页面不止这一种。
比如中国青年网(详见 http://news.youth.cn/gn/), 它的分页部分是由 JavaScript生成的,并非原始 HTML 代码,这其中并不包含 Ajax请求 。 比如 ECharts 的官方实例(详见 http://echarts.baidu.com/demo.html#bar-negative ),其图形都是经过 JavaScript计算之 后生成的。 再有淘宝这种页面,它即使是 Ajax获取的数据,但是其 Ajax接口含有很多加密参数,我 一一 们难以直接找出其规律,也很难直接分析 人jax来抓取
解决:使用模拟浏览器运行方式来实现,这样就可以做到在浏览器中看到是什么样,抓取的源码就是什么样,也即可见即可爬,这样就不用管网页内部的javascript用了什么渲染页面,不管网页后台的Ajax接口到底有哪些参数。
Python提供了许多模拟浏览器运行的库,如 Selenium、 Splash、 PyV8, Ghost等
7.1 Selenium 的使用
Selenium是一个 自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作, 同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。
基本使用
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
browser = webdriver.Chrome()
try:
browser.get('https://www.baidu.com')
input = browser.find_element_by_id('kw') # 找到输入框,根据id获取
input.send_keys('Python')
input.send_keys(Keys.ENTER)
wait = WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'content_left'))) # 里面要是一个元祖
print(browser.current_url)
print(browser.get_cookies())
print(browser.page_source)
except:
print('Fail')
finally:
browser.close()
3. 声明浏览器对象
from selenium import webdriver
browser = webdriver.Chrome() # google
browser = webdriver.Firefox() # 火狐
browser = webdriver.Edge()
browser = webdriver.PhantomJS() # 无界面
browser = webdriver.Safari() # mac自带浏览器
4. 访问页面
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.taobao.com') # 通过get(url)
print(browser.page_source)
browser.close()
5. 查找节点
目的:找到输入框
·单个节点
淘宝
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input_first = browser.find_element_by_id('q') # id方式
input_second = browser.find_element_by_css_selector('#q') # css方式
input_third = browser.find_element_by_xpath('//*[@id="q"]') # xpath方式
print(input_first,input_second,input_third)
browser.close()
Selenium还提供了通用方法 find_element(),它需要传入两个参数: 查找方式 By和值。 实 际上,它就是 find_element_by_id()这种方法的通用函数版本,比如 find_element_by_id(id)就等价 于 find_element(By.ID, id)
·多个节点
find_element() 只能查找目标网页中的一个,要查找多个要用find_elements()
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
lis = browser.find_elements_by_css_selector('.service-bd li')
print(lis)
browser.close()
6. 节点交互
http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement
输入文字:send_keys()
清空文字:clear()
点击按钮:click()
from selenium import webdriver
import time
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input = browser.find_element_by_id('q')
input.send_keys('iphone')
time.sleep(1)
input.clear()
input.send_keys('ipad')
button = browser.find_element_by_class_name('btn-search')
button.click()
淘宝要登陆,后面的看不到结果
7. 动作链
执行鼠标拖曳 、 键盘按键等动作
from selenium import webdriver from selenium.webdriver import ActionChains browser = webdriver.Chrome() url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' browser.get(url) browser.switch_to.frame('iframeResult') source = browser.find_element_by_css_selector('#draggable') target = browser.find_element_by_css_selector('#droppable') actions = ActionChains(browser) actions.drag_and_drop(source, target) actions.perform()
8 .执行javascript
对于没有提供的操作,如下拉进度条,可以使用excute_script()方法实现。
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")') # 下拉到底部后,谈出alert提示框
9. 获取节点信息
page_source 属性可以获取网页的源代码,然后通过Beautiful soup pyquery进行信息提取
也可以使用selenium自带的获取属性、文本等
· 获取属性