动态网页爬虫

什么是动态网页爬虫和AJAX技术:

  1. 动态网页,是网站在不重新加载的情况下,通过ajax技术动态更新网站中的局部数据。比如拉勾网的职位页面,在换页的过程中,url是没有发生改变的,但是职位数据动态的更改了。
  2. AJAX(Asynchronouse JavaScript And XML)异步JavaScript和XML。前端与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。传统的网页(不使用Ajax)如果需要更新内容,必须重载整个网页页面。因为传统的在传输数据格式方面,使用的是XML语法。因此叫做AJAX,其实现在数据交互基本上都是使用JSON。使用AJAX加载的数据,即使使用了JS,将数据渲染到了浏览器中,在右键->查看网页源代码还是不能看到通过ajax加载的数据,只能看到使用这个url加载的html代码。

动态网页爬虫的解决方案:

  1. 直接分析ajax调用的接口。然后通过代码请求这个接口。
  2. 使用Selenium+chromedriver模拟浏览器行为获取数据。

selenium和chromedriver:

使用selenium关闭浏览器:

  1. driver.close():关闭当前的页面。
  2. driver.quit():关闭整个浏览器。

selenium定位元素:

  1. find_element_by_id:根据id来查找某个元素。
  2. find_element_by_class_name:根据类名查找元素。
  3. find_element_by_name:根据name属性的值来查找元素。
  4. find_element_by_tag_name:根据标签名来查找元素。
  5. find_element_by_xpath:根据xpath语法来获取元素。
  6. find_element_by_css_selector:根据css选择器选择元素。

要注意,find_element是获取第一个满足条件的元素。find_elements是获取所有满足条件的元素。

selenium获取当前页面response selenium获取xhr_加载


selenium获取当前页面response selenium获取xhr_chrome_02

selenium表单操作:

  1. webelement.send_keys:给输入框填充内容。
  2. webelement.click:点击。
  3. 操作select标签:需要首先用from selenium.webdriver.support.ui import Select来包装一下选中的对象,才能进行select选择:
  • select_by_index:按索引进行选择。
  • select_by_value:按值进行选择。
  • select_by_visible_text:按照可见文本进行选择。

selenium行为链:

有时候在页面中的操作可能要有很多步,那么这时候可以使用鼠标行为链类selenium.webdriver.common.action_chains.ActionChains来完成。比如现在要将鼠标移动到某个元素上并执行点击事件。那么示例代码如下:

inputTag = driver.find_element_by_id('kw')
submitTag = driver.find_element_by_id('su')
actions = ActionChains(driver)
actions.move_to_element(inputTag)
actions.send_keys_to_element(inputTag,'python')
actions.move_to_element(submitTag)
actions.click(submitTag)
actions.perform()

还有更多的鼠标相关的操作。

click_and_hold(element):点击但不松开鼠标。

context_click(element):右键点击。

double_click(element):双击。

下面是B站的登录和拖拉验证滑条。

selenium获取当前页面response selenium获取xhr_数据_03


下面是键盘操作

selenium获取当前页面response selenium获取xhr_chrome_04


设置浏览器的参数是在定义driver的时候设置chrome_options参数,该参数是一个Options类所实例化的对象。

其中的参数是设置浏览器是否可视化和请求头等信息。

selenium获取当前页面response selenium获取xhr_加载_05


浏览器多窗口切换是在同一个浏览器中切换不同的网页窗口。

selenium获取当前页面response selenium获取xhr_加载_06


Selenium提供了一些延时功能

隐形等待是在一个设定的时间内检测网页是否加载完成,也就是浏览器标签栏的小圈不再转才会执行下一步。

显性等待能够根据判断条件而进行灵活等待,程序每隔一定时间检测一次,如果结果和检测条件成立了会执行下一步。显性等待的使用涉及多个模块:

By:设置元素定位方式。分别是ID、XPATH、LINK_TEXT、NAME等等。

expected_conditions:验证网页元素是否存在。

WebDriverWait的参数说明如下:driver:浏览器对象driver;timeout:超时时间;poll_frequency:检测时间间隔;

ignored_exceptions:忽略的异常。until:条件判断,参数必须为expected_conditions对象。

selenium获取当前页面response selenium获取xhr_加载_07

更多方法请参考:http://selenium-python.readthedocs.io/api.html

为什么需要行为链条?
因为有些网站可能会在浏览器端做一些验证行为是否符合人类的行为来做反爬虫。这时候我们就可以使用行为链来模拟人的操作。行为链有更多的复杂操作,比如双击,右键等,在自动化测试中非常有用。

操作cookie:

  1. 获取所有的cookie:
for cookie in driver.get_cookies():
    print(cookie)
  1. 根据cookie的key获取value:
value = driver.get_cookie(key)
  1. 删除所有的cookie:
driver.delete_all_cookies()
  1. 删除某个cookie:
driver.delete_cookie(key)
  1. 添加cookie:
driver.add_cookie({“name”:”username”,”value”:”abc”})

selenium获取当前页面response selenium获取xhr_加载_08

隐式等待和显式等待:

  1. 隐式等待:指定一个时间,在这个时间内一直会处于等待状态。隐式等待需要使用driver.implicitly_wait
  2. 显式等待:指定在某个时间内,如果某个条件满足了,那么就不会再等待,如果在指定的时间内条件都不满足,那么就不会再等待了。显式等待用的方法是from selenium.webdriver.support.ui import WebDriverWait。示例代码如下:
driver.get("https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc")
WebDriverWait(driver,100).until(
    EC.text_to_be_present_in_element_value((By.ID,"fromStationText"),"长沙")
)
WebDriverWait(driver,100).until(
    EC.text_to_be_present_in_element_value((By.ID,"toStationText"),"北京")
)
btn = driver.find_element_by_id("query_ticket")
btn.click()

打开新窗口和切换页面:

  1. selenium中没有专门的打开新窗口的方法,是通过window.execute_script()来执行js脚本的形式来打开新窗口的。
window.execute_script("window.open('https://www.douban.com/')")
  1. 打开新的窗口后driver当前的页面依然还是之前的,如果想要获取新的窗口的源代码,那么就必须先切换过去。示例代码如下:
window.switch_to.window(driver.window_handlers[1])

设置代理:

设置代理通过ChromeOptions来设置,示例代码如下:

options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://110.52.235.176:9999")
driver = webdriver.Chrome(executable_path="D:\ProgramApp\chromedriver\chromedriver73.exe",chrome_options=options)

driver.get("http://httpbin.org/ip")

补充:

  1. get_property:获取html标签中官方写好的属性。
  2. get_attribute:获取html标签中官方和非官方的属性。
  3. driver.save_screenshoot:获取当前页面的截图,有时候请求失败了,那么可以把当前网页的截图保存下来,方便后期进行分析。