selenium抓取动态⽹页数据
1.selenium抓取动态⽹页数据基础介绍
1.1 什么是AJAX
  AJAX(Asynchronouse JavaScript And XML:异步JavaScript和XML)通过在后台与服务器进⾏少量数据交换,Ajax 可以使⽹页实现异步更新,这意味着可以在不重新加载整个⽹页的情况下,对⽹页的某部分进⾏局部更新。传统的⽹页(不使⽤Ajax)如果需要更新内容,必须重载整个⽹页页⾯。
  因为传统的⽹页在传输数据格式⽅⾯,使⽤的是XML语法,因此叫做AJAX,其实现在数据交互基本上都是使⽤JSON。使⽤AJAX加载的数据,即使使⽤了JS将数据渲染到了浏览器中,在右键->查看⽹页源代码还是不能看到通过ajax加载的数据,只能看到使⽤这个url加载的html代码。
1.2 获取ajax数据的⽅式
  法1:直接分析ajax调⽤的接⼝。然后通过代码请求这个接⼝。
  法2:使⽤Selenium+chromedriver模拟浏览器⾏为获取数据。
⽅式优点缺点
分析接⼝直接可以请求到数据。不需要做⼀些解析⼯作。代码量少,性能⾼。分析接⼝⽐较复杂,特别是⼀些通过js混淆的接⼝,要有⼀定的js功底。容易被发现是爬⾍。
selenium 直接模拟浏览器的⾏为。浏览器能请求到的,使⽤selenium也能请
求到。爬⾍更稳定。
代码量多。性能低。
1.3 Selenium+chromedriver获取动态数据
  Selenium相当于是⼀个机器⼈。可以模拟⼈类在浏览器上的⼀些⾏为,⾃动处理浏览器上的⼀些⾏为,⽐如点击,填充数据,删除cookie等。chromedriver是⼀个驱动Chrome浏览器的驱动程序,使⽤他才可以驱动浏览器。当然针对不同的浏览器有不同的driver。以下列出了不同浏览器及其对应的driver:
1. Chrome:
2. Firefox:
3. Edge:
4. Safari:
1.4 安装Selenium和chromedriver
1. 安装Selenium:Selenium有很多语⾔的版本,有java、ruby、python等。我们下载python版本的就可以了。
pip install selenium
2. 安装chromedriver:下载完成后,放到不需要权限的纯英⽂⽬录下就可以了。
1.5 快速⼊门
  现在以⼀个简单的获取百度⾸页的例⼦来讲下Selenium和chromedriver如何快速⼊门:
from selenium import webdriver
# chromedriver的绝对路径
driver_path = r'D:\ProgramApp\'
# 初始化⼀个driver,并且指定chromedriver的路径
driver = webdriver.Chrome(executable_path=driver_path)
# 请求⽹页
<("www.baidu/")
# 通过page_source获取⽹页源代码
print(driver.page_source)
1.6 selenium常⽤操作
#-*-coding = utf-8 -*-
from selenium import webdriver
from selenium.webdrivermon.by import By
# chromedriver的绝对路径
driver_path = r'D:\ProgramApp\'
# 初始化⼀个driver,并且指定chromedriver的路径
driver = webdriver.Chrome(executable_path=driver_path)
# 请求⽹页
<("www.baidu/")
# 通过page_source获取⽹页源代码
print(driver.page_source)
selenium常⽤操作
1.关闭页⾯:
driver.close():关闭当前页⾯。
driver.quit():退出整个浏览器。
2.定位元素:
a)find_element_by_id:根据id来查某个元素。等价于:
submitTag = driver.find_element_by_id('su')
submitTag1 = driver.find_element(By.ID,'su')
b)find_element_by_class_name:根据类名查元素。等价于:
submitTag = driver.find_element_by_class_name('su')
submitTag1 = driver.find_element(By.CLASS_NAME,'su')
c)find_element_by_name:根据name属性的值来查元素。等价于:
submitTag = driver.find_element_by_name('email')
submitTag1 = driver.find_element(By.NAME,'email')
d)find_element_by_tag_name:根据标签名来查元素。等价于:
submitTag = driver.find_element_by_tag_name('div')
submitTag1 = driver.find_element(By.TAG_NAME,'div')
e)find_element_by_xpath:根据xpath语法来获取元素。等价于:
submitTag = driver.find_element_by_xpath('//div')
submitTag1 = driver.find_element(By.XPATH,'//div')
f)find_element_by_css_selector:根据css选择器选择元素。等价于:
submitTag = driver.find_element_by_css_selector('//div')
submitTag1 = driver.find_element(By.CSS_SELECTOR,'//div')
要注意,find_element是获取第⼀个满⾜条件的元素。find_elements是获取所有满⾜条件的元素。
3.操作表单元素:
a)操作输⼊框:分为两步。第⼀步:到这个元素。第⼆步:使⽤send_keys(value),将数据填充进去。⽰例代码如下:
inputTag = driver.find_element_by_id('kw')
inputTag.send_keys('python')
使⽤clear⽅法可以清除输⼊框中的内容。⽰例代码如下:
inputTag.clear()
b)操作checkbox:因为要选中checkbox标签,在⽹页中是通过⿏标点击的。因此想要选中checkbox标签,那么先选中这个标签,然后执⾏click事件。⽰例代码如下:
码如下:
rememberTag = driver.find_element_by_name("rememberMe")
rememberTag.click()
c)选择select:select元素不能直接点击。因为点击后还需要选中元素。这时候selenium就专门为select
标签提供了⼀个类
selenium.webdriver.support.ui.Select。将获取到的元素当成参数传到这个类中,创建这个对象。以后就可以使⽤这个对象进⾏选择了。⽰例代码如下:
from selenium.webdriver.support.ui import Select
# 选中这个标签,然后使⽤Select创建对象
selectTag = Select(driver.find_element_by_name("jumpMenu"))
# 根据索引选择
selectTag.select_by_index(1)
# 根据值选择
selectTag.select_by_value("www.95yueba")
# 根据可视的⽂本选择
selectTag.select_by_visible_text("95秀客户端")
# 取消选中所有选项
selectTag.deselect_all()
d)操作按钮:操作按钮有很多种⽅式。⽐如单击、右击、双击等。这⾥讲⼀个最常⽤的。就是点击。直接调⽤click函数就可以了。⽰例代码如下:
inputTag = driver.find_element_by_id('su')
inputTag.click()
4.⾏为链:
有时候在页⾯中的操作可能要有很多步,那么这时候可以使⽤⿏标⾏为链类ActionChains来完成。⽐如现在要将⿏标移动到某个元素上并执⾏点击事件。那么⽰例代码如下:
inputTag = driver.find_element_by_id('kw')
submitTag = driver.find_element_by_id('su')
actions = ActionChains(driver)
actions.send_keys_to_element(inputTag,'python')
actions.click(submitTag)
actions.perform()
还有更多的⿏标相关的操作:
click_and_hold(element):点击但不松开⿏标。
context_click(element):右键点击。
double_click(element):双击。
更多⽅法请参考:adthedocs.io/api.html
常⽤操作1
#-*-coding = utf-8 -*-
from selenium import webdriver
from selenium.webdrivermon.by import By
# chromedriver的绝对路径
driver_path = r'E:\study\'
# 初始化⼀个driver,并且指定chromedriver的路径
driver = webdriver.Chrome(executable_path=driver_path)
# 请求⽹页
<("www.baidu/")
# 通过page_source获取⽹页源代码
print(driver.page_source)
# 5.Cookie操作:
# a)获取所有的cookie:
for cookie _cookies():
print(cookie)
# b)根据cookie的key获取value:
#value = _cookie(key)
_cookie('PSTM'))
# c)删除所有的cookie:
driver.delete_all_cookies()
# d)删除某个cookie:
#driver.delete_cookie(key)
# 6页⾯等待:
# 现在的⽹页越来越多采⽤了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页⾯等待时间过长导致某个dom元素还没出来,但是你的代码直接使⽤了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题。所以 Selenium 提供了两种等待⽅式:⼀种是隐式等待、⼀种是显式等待。
# a)隐式等待:调⽤driver.implicitly_wait。那么在获取不可⽤的元素之前,会先等待10秒中的时间。⽰例代码如下:
driver = webdriver.Chrome(executable_path=driver_path)
driver.implicitly_wait(10)
# 请求⽹页
<("www.douban/")
# b)显⽰等待:显⽰等待是表明某个条件成⽴后才执⾏获取元素的操作。也可以在等待的时候指定⼀个最⼤的时间,如果超过这个时间那么就抛出⼀个异常。显⽰等待应该使⽤selenium.pted_conditions期望的条件和selenium.webdriver.support.ui.WebDriverWait来配合完成。⽰例代码如下:
from selenium import webdriver
from selenium.webdrivermon.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
<("somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
# ⼀些其他的等待条件:
# presence_of_element_located:某个元素已经加载完毕了。
# presence_of_all_emement_located:⽹页中所有满⾜条件的元素都加载完毕了。
# element_to_be_cliable:某个元素是可以点击了。
# 更多条件请参考:adthedocs.io/waits.html
常⽤操作2
7.页⾯切换
有时候窗⼝中有很多⼦tab页⾯。这时候肯定是需要进⾏切换的。selenium提供了⼀个叫做switch_to_window来进⾏切换,具体切换到哪个页⾯,可以从driver.window_handles中到。⽰例代码如下:
# 打开⼀个新的页⾯
print(driver.window_handles)
# 切换到这个新的页⾯中
driver.switch_to_window(self.driver.window_handles[1])
print(driver.current_url)
#注意
#虽然在浏览器窗⼝中切换到了新的页⾯,但是driver中还没有切换
#如果想要在代码中切换到新的界⾯,那么应该使⽤driver.switch_to_window来切换到指定的窗⼝
#从driver.window_handles中取出具体第⼏个窗⼝
#driver.window_handles是⼀个列表,⾥⾯装的都是窗⼝句柄,它会按照打开的页⾯顺序来存储窗⼝的句柄。
8.设置代理ip
有时候频繁爬取⼀些⽹页。服务器发现你是爬⾍后会封掉你的ip地址。这时候我们可以更改代理ip。更改代理ip,不同的浏览器有不同的实现⽅式。这⾥以Chrome浏览器为例来讲解:
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=110.73.2.248:8123")
driver_path = r"D:\ProgramApp\"
driver = webdriver.Chrome(executable_path=driver_path,chrome_options=options)
<('/ip')
9. WebElement元素
from webelement import WebElement类是每个获取出来的元素的所属类。
有⼀些常⽤的属性:
get_attribute:这个标签的某个属性的值。
screentshot:获取当前页⾯的截图。这个⽅法只能在driver上使⽤。
driver的对象类,也是继承⾃WebElement。
常⽤操作3
1.7 爬取拉钩⽹职位信息
import requests
from lxml import etree
import time
import re
headers = {
"Accept":"application/json, text/javascript, */*; q=0.01",
"Accept-Encoding":"gzip, deflate, br",
"Accept-Language":"zh-CN,zh;q=0.9",
"Connection":"keep-alive",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36", "Referer":"www.lagou/jobs/list_python?labelWords=&fromSearch=true&suginput=",
"Origin":"www.lagou",
"Host":"www.lagou",
"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8",
"Cookie":"_ga=GA1.2.1602115737.1553064534; user_trace_token=20190320144853-39b1375a-4adc-11e9-a253-525400f775ce;
LGUID=20190320144853-39b13f88-4adc-11e9-a253-525400f775ce; WEBTJ-ID=20190408120043-169fb1afd63488-06179b118ca307-7a1437-2073600-169fb1afd648ed; _gid=GA1.2.1826141825.1554696044; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22169fb1bb2c41ea-04951e55adc96a-7a1437-2073600-169fb1bb2c58d0%22%2C%22%24device_id%22%3A%22169fb1bb2c41ea-04951e55adc96a-7a1437-2073600-169fb1bb2c58d0%22%7D; sajssdk_2015_cross_new_user=1; _putrc=4C5D2603888320CA;
selenium获取cookie
JSESSIONID=ABAAABAAADEAAFIB00F5DDE71D51610901CB9E0031812BA; login=true; unick=%E4%BC%8D%E6%99%93%E4%B8%BD; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=49;