动态网页数据抓取
Ajax(Asynchronouse JavaScript And XML)异步JavaScript和XML。在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新,意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。传统的网页(不使用Ajax)如果需要更新内容,必须重新加载整个页面。过去网页在传输数据格式方面,使用的是XML语法。因此叫做Ajax。现在数据交互基本上都是使用Json(PS:在武汉理工招聘会上我遇到个面试官(应该是CTO)讨论json问题听的实在舒服!听他说话比听课都舒服!)。使用Ajax加载的数据,即使使用了js,将数据渲染到浏览器中,在【右键】->【查看网页源代码】还是不能看到通过Ajax加载的数据,只能看到使用这个url加载的HTML代码。
获取Ajax数据的方式:
1.分析Ajax调用的接口,通过代码求情接口获得数据。
2.使用selenium + chromedriver/geckodriver 模拟浏览器行为获取数据。
方式 | 优点 | 缺点 |
---|---|---|
分析接口 | 直接可以请求到数据,不需要做解析工作。代码量少,性能高。 | 分析接口比较复杂,特别是通过js混淆的接口,要有一定的js基础,容易被识别是爬虫程序 |
Selenium | 直接模拟浏览器行为,浏览器能请求到的,使用selenium也能请求到,爬虫更稳定 | 代码量多,性能低 |
Selenium+chromedriver获取动态数据:
Selenium相当于一个机器人,可以模拟人在浏览器上的行为,自动处理浏览器行为,比如点击,填充数据,删除cookie等,chromedriver是一个驱动chrome浏览器的驱动程序,使用它才可以驱动浏览器。针对不同的浏览器有不同的driver:
selenium常用操作:
-
关闭操作:
driver.close()
:关闭当前标签页面driver.quit()
:退出整个浏览器
-
定位操作:
from selenium import webdriver from selenium.webdriver.common.by import By # 1. find_element_by_id:根据标签id定位元素: input_tag = driver.find_element_by_id("form_email") input_tag = driver.find_element(By.ID, "form_email") # 2. find_element_by_class_name:根据类名查找元素: input_tag = driver.find_element_by_class_name("inp") input_tag = driver.find_element(By.CLASS_NAME, "inp") # 3. find_element_by_name:根据name属性值查找元素: input_tag = driver.find_element_by_name("form_email") input_tag = driver.find_element(By.NAME, "form_email") # . find_element_by_tag_name:根据标签名来查找元素: input_tag = driver.find_element_by_tag_name("div") input_tag = driver.find_element(By.TAG_NAME, "div") # 5. find_element_by_xpath:根据xpath语法查找元素: input_tag = driver.find_element_by_xpath("//*[@id='form_email']") input_tag = driver.find_element(By.XPATH, "//*[@id='form_email']") # 6. find_element_by_css_selector:根据css选择器选择元素: input_tag = driver.find_element_by_css_selector("#form_email") input_tag = driver.find_element_(By.CSS_SELECTOR, "#form_email") # 7. find_element_by_link_text:根据文本选择 input_tag = driver.find_element_by_link_text("登录") input_tag = driver.find_element(By.LINK_TEXT, "登录")
-
操作表单:
-
操作输入框:
- a)输入框输入数据:定位->输入
usrTag = driver.find_element_by_name("form_email") usrTag.send_keys(user["username"])
- b)输入框清除数据:
usrTag.clear()
- a)输入框输入数据:定位->输入
-
操作checkbox:
remembermeTag = driver.find_element_by_name("remember") remembermeTag.click()
-
选择select:
- select元素不能直接点击,因为点击后还需要选中元素。这时候selenium专门为select标签提供了一个类
selenium.webdriver.support.ui.Select
。将获取到的元素当成参数传递到这个类中,创建这个对象,就可以使用这个对象进行选择了。from selenium.webdriver.support.ui import Select driver.get("http://jwc.whsw.cn/") selectTag = Select(driver.find_element_by_name("jumpMenu")) selectTag.select_by_index(10) # 根据索引选择 selectTag.select_by_value("http://jsjx.whsw.cn/") # 根据value值选择 selectTag.select_by_visible_text("计算机与信息工程学院") # 根据可视文本选择 selectTag.deselect_all() # 取消选中的所有选项
- select元素不能直接点击,因为点击后还需要选中元素。这时候selenium专门为select标签提供了一个类
-
-
行为链:
有时候在页面中可能需要很多步,那么这时可以使用鼠标行为链ActionChains
来完成,比如要将鼠标光标移动到某个元素上执行事件:# # ------------------------ # # 行为链 # # ------------------------ driver.get("https://www.baidu.com/") inputTag = driver.find_element_by_name("wd") 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() # Performs all stored actions.
更多教程:https://selenium-python.readthedocs.io/
-
Cookie操作:
# 1. 获取所有的cookie: for cookie in driver.get_cookies(): print(cookie) # 2. 根据cookie的key获得value: # Get a single cookie by name. Returns the cookie if found, None if not. print(driver.get_cookie("PSTM")) # 3. 删除所有cookie: # Delete all cookies in the scope of the session. driver.delete_all_cookies() # 4. 删除某个cookie: # Deletes a single cookie with the given name. driver.delete_cookie("BIDUPSID")
-
页面等待:
网页越来越多采用Ajax技术,这样程序便不能确定何时某个元素完全加载出来了,如果实际页面等待时间过长导致某个demo元素还没出来,但是代码直接使用了这个WebElement
,那么就会抛出NullPointer的异常,为了解决这个问题,selenium提供了两种等待方式:隐式等待、显式等待-
隐式等待:
调用driver.implicitly_wait
。那么在获取不可用的元素之前,会先等待指定时间 -
显式等待:
显式等待就是表明某个条件成立后才执行获取元素的操作,也可以在等待的时候指定一个最大时间,如果超过这个时间那么就抛出一个异常。显式等待应该用selenium.webdriver.support.extended_conditions
期望的条件和selenium.webdriver.support.ui.WebDriverWait
来配合完成。
-
-
页面切换:
Selenium提供了switch_to_window
进行标签页切换,具体切换到哪个标签页,可以通过driver.window_handles
中找到。driver.get("https://www.baidu.com") driver.get("https://www.douban.com") driver.execute_script("window.open('https://www.baidu.com')") # Synchronously Executes JavaScript in the current window/frame. print(driver.current_url) # driver.switch_to_window(driver.window_handles[1]) # 旧版本 driver.switch_to.window(driver.window_handles[1]) # 标签切换 print(driver.current_url)
-
使用代理IP(chrome浏览器):
options = webdriver.ChromeOptions() options.add_argument("--proxy-server=http://183.47.2.201:43174") driver = webdriver.Chrome(executable_path=chromediver_path, chrome_options=options) driver.get("https://httpbin.org/ip")
-
WebElement元素:
driver = webdriver.Chrome(executable_path=chromediver_path) driver.get("https://www.baidu.com") submitBtn = driver.find_element_by_id("su") print(type(submitBtn)) # <class 'selenium.webdriver.remote.webelement.WebElement'> print(submitBtn.tag_name) print(submitBtn.get_property("value")) print(submitBtn.get_attribute("value"))
更多关于WebElement:
https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement