小言_互联网的博客

selenium自动化测试工具的爬虫之旅

498人阅读  评论(0)

Selenium是一个自动化测试工具,可以驱动浏览器器执行特定的动作,如点击,下拉等。同时还可以获取浏览器当前呈现页面的源代码,可见即可爬。

浏览器驱动

根据自己的浏览器进行选择:

Chrome: https://sites.google.com/a/chromium.org/chromedriver/downloads

Firefox: https://github.com/mozilla/geckodriver/releases

 

使用selenium写爬虫

优势

* 不需要做复杂的抓包、构造请求、解析数据等,开发难度相对要低一些。

* 其访问参数跟使用浏览器的正常用户一模一样,访问行为也相对更像正常用户,不容易被反爬虫策略命中。

* 生成的浏览器环境可以自动运行 JS 文件,所以不用担心如何逆向混淆过的JS文件生成用作人机校验的参数,如马蜂窝酒店评论的人机校验参数_sn,网易云音乐评论的人机校验参数params、encSecKey。可以自行抓包查看。

* 如果需要抓取同一个前端页面上面来自不同后端接口的信息,如OTA酒店详情页的酒店基础信息、价格、评论等,使用Selenium可以在一次请求中同时完成对三个接口的调用,相对方便

 

劣势

相比于抓包→构造请求→解析返回值的爬虫,由于Selenium需要生成一个浏览器环境,所有操作(与元素交互、获取元素内容等)均需要等待页面加载完毕后才可以继续进行,所以速度相比构造请求的慢很多。

对于为了反爬做了特殊处理的展示内容,如字体加密(参考猫眼)、图片替换数字(参考自如)等,可能取不到想要的数据。

 

准备

以Firefox为例来研究selenium的用法, 在开始之前,请确保已经正确安装好Firefox浏览器并配置好了GeckoDriver;另外,还需要正确安装Python的Selenium库

初步体验


  
  1. from selenium import webdriver
  2. browser = webdriver.Firefox()
  3. browser.get( 'http://www.baidu.com/')

运行这段代码,会自动打开浏览器,然后访问百度。

如果程序执行错误,浏览器没有打开,那么应该是没有装 Firefox浏览器或者 Firefox驱动没有配置在环境变量里。下载驱动,然后将驱动文件路径配置在环境变量即可

模拟提交

首先等页面加载完成,然后输入到搜索框文本,点击提交。


  
  1. from selenium import webdriver
  2. from selenium.webdriver.common.keys import Keys
  3. driver = webdriver.Firefox()
  4. driver.get( "http://www.python.org")
  5. assert "Python" in driver.title
  6. elem = driver.find_element_by_name( "q")
  7. elem.send_keys( "pycon")
  8. elem.send_keys(Keys.RETURN)
  9. print(driver.page_source)

页面操作

页面交互

要做到页面交互,比如点击,输入等, 前提就是要找到页面中的元素。WebDriver提供了各种方法来寻找元素。

Eg:

<input type="text" name="passwd" id="passwd-id" />

  
  1. element = driver.find_element_by_id( "passwd-id")
  2. element = driver.find_element_by_name( "passwd")
  3. element = driver.find_elements_by_tag_name( "input")
  4. element = driver.find_element_by_xpath( "//input[@id='passwd-id']")

在用 xpath 的时候还需要注意的是,如果有多个元素匹配了 xpath,它只会返回第一个匹配的元素。如果没有找到,那么会抛出 NoSuchElementException 的异常。

获取了元素之后,下一步当然就是向文本输入内容了,可以利用下面的方法

element.send_keys("some text")

同样你还可以利用 Keys 这个类来模拟点击某个按键。

element.send_keys("and some", Keys.ARROW_DOWN)

你可以对任何获取到到元素使用 send_keys 方法,就像你在 GMail 里面点击发送键一样。不过这样会导致的结果就是输入的文本不会自动清除。所以输入的文本都会在原来的基础上继续输入。你可以用下面的方法来清除输入文本的内容

element.clear()

这样输入的文本会被清除

填充表单

下拉选项卡处理方式


  
  1. element = driver.find_element_by_xpath( "//select[@name='name']")
  2. all_options = element.find_elements_by_tag_name( "option")
  3. for option in all_options:
  4. print( "Value is: %s" % option.get_attribute( "value"))
  5. option.click()

首先获取了第一个 select 元素,也就是下拉选项卡。然后轮流设置了 select 选项卡中的每一个 option 选项。你可以看到,这并不是一个非常有效的方法。

 

其实 WebDriver 中提供了一个叫 Select 的方法,可以帮助我们完成这些事情。


  
  1. from selenium.webdriver.support.ui import Select
  2. select = Select(driver.find_element_by_name( 'name'))
  3. select.select_by_index(index)
  4. select.select_by_visible_text( "text")
  5. select.select_by_value(value)

 

全部取消选择怎么办呢?很简单


  
  1. select = Select(driver.find_element_by_id( 'id'))
  2. select.deselect_all()

获取所有的已选选项


  
  1. select = Select(driver.find_element_by_xpath( "xpath"))
  2. all_selected_options = select.all_selected_options

获取所有可选选项

options = select.options

提交表单

driver.find_element_by_id("submit").click()

相当于模拟点击了 submit 按钮,做到表单提交

 

页面切换

一个浏览器肯定会有很多窗口,所以我们肯定要有方法来实现窗口的切换

driver.switch_to_window("windowName")

另外还可以使用 window_handles 方法来获取每个窗口的操作对象


  
  1. for handle in driver.window_handles:
  2. driver.switch_to_window(handle)

操作页面的前进和后退功能


  
  1. driver.forward()
  2. driver.back()

 

元素选取

关于元素的选取,有如下api


  
  1. * find_element_by_id
  2. * find_element_by_name
  3. * find_element_by_xpath
  4. * find_element_by_link_text
  5. * find_element_by_partial_link_text
  6. * find_element_by_tag_name
  7. * find_element_by_class_name
  8. * find_element_by_css_selector

 


  
  1. * find_elements_by_name
  2. * find_elements_by_xpath
  3. * find_elements_by_link_text
  4. * find_elements_by_partial_link_text
  5. * find_elements_by_tag_name
  6. * find_elements_by_class_name
  7. * find_elements_by_css_selector

另外还可以利用 By 类来确定哪种选择方式


  
  1. from selenium.webdriver.common.by import By
  2. driver.find_element(By.XPATH, '//button[text()="Some text"]')
  3. driver.find_elements(By.XPATH, '//button')

 

By 类的一些属性如下


  
  1. ID = "id"
  2. XPATH = "xpath"
  3. LINK_TEXT = "link text"
  4. PARTIAL_LINK_TEXT = "partial link text"
  5. NAME = "name"
  6. TAG_NAME = "tag name"
  7. CLASS_NAME = "class name"
  8. CSS_SELECTOR = "css selector"

 

页面等待

Selenium 提供了两种等待方式,一种是隐式等待,一种是显式等待。 隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行。


  
  1. 显示等待
  2. from selenium.webdriver.support import expected_conditions as EC
  3. wait = WebDriverWait(driver, 10)
  4. element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))
  5. 其他的等待条件
  6. * title_is
  7. * title_contains
  8. * presence_of_element_located
  9. * visibility_of_element_located
  10. * visibility_of
  11. * presence_of_all_elements_located
  12. * text_to_be_present_in_element
  13. * text_to_be_present_in_element_value
  14. * frame_to_be_available_and_switch_to_it
  15. * invisibility_of_element_located
  16. * element_to_be_clickable – it is Displayed and Enabled.
  17. * staleness_of
  18. * element_to_be_selected
  19. * element_located_to_be_selected
  20. * element_selection_state_to_be
  21. * element_located_selection_state_to_be
  22. * alert_is_present
  23. 隐式等待
  24. 隐式等待比较简单,就是简单地设置一个等待时间,单位为秒。
  25. driver.implicitly_wait( 10)

 

简单的爬虫示例

爬取Amazon某一类商品图片URL及产品的基本讯息


  
  1. from selenium import webdriver
  2. option = webdriver.FirefoxOptions()
  3. # option.add_argument('--headless') #无头模式
  4. option.set_preference( 'permissions.default.image', 2) #不加载图片
  5. # option.set_preference('permissions.default.stylesheet', 2)
  6. driver = webdriver.Firefox(options=option)
  7. driver.get( 'https://www.amazon.com/s?bbn=13861679011&rh=n%3A3760911%2Cn%3A%2111055981%2Cn%3A17242866011%2Cn%3A11063461%2Cn%3A13861679011%2Cp_36%3A10000-200000&qid=1581758015&rnid=386662011&ref=lp_13861679011_nr_p_36_4')
  8. def get_product_conf(max_num):
  9. global id,CSV_headers,random_str_list
  10. for i in range(max_num):
  11. id = id + 1
  12. # print(i.get_attribute('href'))
  13. product_img = driver.find_element_by_xpath( '//span/div[@class="s-result-list s-search-results sg-row"]/div[%d]//img[@class="s-image"]' %(i+ 1))
  14. print(product_img.get_attribute( 'src'))
  15. try:
  16. driver.find_element_by_xpath( '//span/div[@class="s-result-list s-search-results sg-row"]/div[%d]' %(i+ 1)).click()
  17. product_title = driver.find_element_by_id( 'productTitle').text
  18. except:
  19. driver.back()
  20. continue
  21. # 商品描述
  22. product_description = driver.find_element_by_id( 'productDescription').text.replace( '\n', '<br/>')
  23. # 商品介绍
  24. product_feature = driver.find_element_by_id( 'feature-bullets').text
  25. # 所属栏位
  26. product_categories = driver.find_element_by_id( 'wayfinding-breadcrumbs_feature_div').text.replace( '\n', '').replace( '›', '>')
  27. print( 'product_title:',product_title)
  28. print( 'product_description:',product_description)
  29. print( 'product_feature:',product_feature)
  30. print( 'product_categories:',product_categories)
  31. driver.back()
  32. if __name__ == '__main__':
  33. id = 1
  34. while True:
  35. print( 'start')
  36. max_num = len(
  37. driver.find_elements_by_xpath( '//span/div[@class="s-result-list s-search-results sg-row"]/div')) - 1
  38. print(max_num)
  39. get_product_conf(max_num)
  40. # data = get_product_conf(max_num)
  41. # write_csv_rows('demo_test.csv', CSV_headers, data)
  42. # print('1111111111111111111111')
  43. if driver.find_elements_by_xpath( '//li[@class="a-last"]/a[@href]'):
  44. print(driver.find_elements_by_xpath( '//li[@class="a-last"]/a[@href]'))
  45. driver.find_element_by_class_name( 'a-last').click()
  46. # print('222222222222222222222')
  47. else:
  48. break
  49. driver.close()

 

 

 

其他常用函数

 

关闭浏览器:quit()

最大化窗口: maximize_window()

设置窗口参数:set_window_size(600,800)

刷新页面: refresh()

 

鼠标事件:

双击:double_click()

右击:context_click()

拖放:drag_and_drop()

悬停:move_to_element()

按下:click_and_hold()

 

键盘事件:

send_keys(Keys.BACK_SPACE) = BackSpace

send_keys(Keys.SPACE) = Space

send_keys(Keys.TAB) = Tab

send_keys(Keys.ESCAPE) = Esc

send_keys(Keys.ENTER) = Enter

send_keys(Keys.CONTROL,‘a’) = Ctrl+A

send_keys(Keys.F1) = 键盘F1

 

多表单切换:switch_to.frame()

多窗口切换:switch_to.window()

当前句柄:current_window_handle

所有句柄:window_handles

警告框处理:switch_to_alert()

text:返回所有alert/confirm/prompt中的文字信息

accept():接受现有警告框

dismiss():解散现有警告框

send_keys(keysToSend):发送文本至警告框

 

cookie处理:

get_cookies():获得所有cookie信息

get_cookie(name):返回字典的key为“name”的cookie信息

add_cookie(cookie_dict):添加cookie。“cookie_dict”指字典对象,必须有name和value值

delete_cookie(name,optionsString):删除cookie信息。“name”是要删除的cookie的名称,“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域”

delete_all_cookies():删除所有cookie信息

 

窗口截图:get_screenshot_as_file()

生成随机数:radint()

 

滚动条设置


  
  1. # 使用scrollTop滑动到底部
  2. js = "var action=document.documentElement.scrollTop=10000"
  3. driver.execute_script(js)
  4. # 使用scrollTo设置位置
  5. driver.set_window_size( 600, 600)
  6. js = "window.scrollTo(100,450);"
  7. driver.execute_script(js)

 

 

 


转载:https://blog.csdn.net/qq_31033037/article/details/104795641
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场