写点什么

用 python selenium 爬简书,Python 自动化领域之 Selenium WebDriver 学习第 2 篇

作者:梦想橡皮擦
  • 2022 年 3 月 01 日
  • 本文字数:3451 字

    阅读完需:约 11 分钟

本篇博客使用 selenium 实现对简书官网的操作。


通过 selenium 执行 JS

selenium 打开网页之后,可以通过 JS 对页面进行修改,例如修改页面标题,代码如下:


from selenium import webdriverfrom selenium.webdriver.chrome.options import Options
opt = Options() # 创建 chrome 参数对象
driver = webdriver.Chrome()
driver.get("http://www.jianshu.com") # 打开简书
js1 = "document.title='我的简书'"driver.execute_script(js1) # 执行JS代码
js2 = "alert($('title').text())"driver.execute_script(js2) # 执行Jquery代码
# driver.quit()
复制代码


测试 JS 与 JQuery 代码在 selenium 访问简书时,都可以运行,但不是所有网站都可以执行 JQ 代码,需目标页面有加载 jquery 文件。


执行 JS 代码的方法为 execute_script,可以在该方法要执行的 JS 代码中,增加 return 关键字,就可以返回 JS 的执行结果。


from selenium import webdriverfrom selenium.webdriver.chrome.options import Options
opt = Options() # 创建 chrome 参数对象
driver = webdriver.Chrome()
driver.get("http://www.jianshu.com") # 打开简书
js1 = "$('title').text()"ret1 = driver.execute_script(js1) # 返回 None

js2 = "return $('title').text()"ret2 = driver.execute_script(js2) # 返回获取到的标题
print(ret1,ret2)
复制代码


execute_script 方法还允许向 JS 传递参数,在 JS 中需要使用关键字 arguments 接收。


from selenium import webdriverfrom selenium.webdriver.chrome.options import Options
opt = Options() # 创建 chrome 参数对象
driver = webdriver.Chrome()
driver.get("http://www.jianshu.com") # 打开简书
js1 = "document.title = arguments[0]"ret1 = driver.execute_script(js1, ("我的简书",))
# driver.quit()
复制代码


更多执行 JS 的效果,在后续博客进行学习。

selenium 实现简书搜索

通过开发者工具查看简书搜索框的 HTML 代码为:


<input  type="text"  name="q"  id="q"  value=""  autocomplete="off"  placeholder="搜索"  class="search-input"  data-mounted="1"/>
复制代码


搜索框可以通过 id="q" 进行定位。搜索按钮的 HTML 代码如下:


<a class="search-btn" href="javascript:void(null)"  ><i class="iconfont ic-search"></i></a>
复制代码


通过 class="search-btn" 进行定位。


基于上述内容,编写搜索页面的跳转代码如下。


from selenium import webdriverfrom selenium.webdriver.chrome.options import Options
opt = Options() # 创建 chrome 参数对象
driver = webdriver.Chrome()
driver.get("http://www.jianshu.com") # 打开简书
search_box = driver.find_element_by_id("q").send_keys("梦想橡皮擦") # 查找搜索框,并输入待查询文本click_btn = driver.find_element_by_class_name('search-btn').click() # 点击搜索按钮
# driver.quit()
复制代码

selenium 隐式与显式等待

在 selenium 中存在显式与隐式两种等待方法,其中核心用到的第一个方法是:


driver.implicitly_wait(30)  # 隐式等待
复制代码


implicitly_wait() 方法表示等待找到元素或者等待命令被完成,设置一次,整个程序都会受到影响,该方法只有一个参数,为等待时间,单位是秒。注意:此方法不能设置 execute_async_script 的等待时间。


from selenium import webdriver
driver = webdriver.Chrome()driver.implicitly_wait(10)
driver.get("http://www.jianshu.com") # 打开简书
container = driver.find_element_by_id("list-container")print(container)
复制代码


隐式等待会一直等待整个页面加载完成,相当于我们浏览网页时,浏览器不再加载为止。


如果希望显式的等待网页元素,可以使用下述代码


显示等待:执行自定义的程序判断条件,如果判断条件成立执行下一步,否则继续等待,直到超过设定的最长等待时间,然后抛出TimeoutError 异常。


from selenium import webdriverfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import By
driver = webdriver.Chrome()driver.implicitly_wait(10)
driver.get("http://www.jianshu.com") # 打开简书
# container = driver.find_element_by_id("list-container") # 隐式等待# print(container)
container = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'list-container')))print(container)
复制代码


在编写前优先导入了 3 个模块


from selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import By
复制代码


其中用到的核心代码如下:


WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'list-container')))
复制代码


接下来依次解释一下相关函数。


WebDriverWait 类的构造函数如下:


def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None)
复制代码


其中参数含义为:


  • driver:WebDriver 对象实例;

  • timeout:超时时间;

  • poll_frequency:调用 untiluntil_not 中的方法的间隔时间,默认是 0.5 秒;

  • ignored_exceptions:可忽略的异常,在调用 untiluntil_not 的过程中,如果出现元组内的异常,则不中断代码,继续等待,如果抛出的是元组外的异常,则中断代码,抛出异常。默认只有 NoSuchElementException


WebDriverWait 对象有两种等待方式,分别为 untiluntil_not,这两个方法的参数一致,如下所示:


  • method:在等待期间,每隔一段时间(poll_frequency)调用这个传入的方法,直到返回值不是 False;

  • message:抛出 TimeoutError 时的错误提示。


其中可执行方法 method 参数,可以传递的值为 expected_conditions 模块中的各种条件,也可以传递 WebElementis_displayed()is_enabled()is_selected() 方法,如果你想自己实现,注意一定要在类中编写 __call__ 方法。


expected_conditionsselenium 的一个模块,包含一系列可用于判断的条件,例如上述代码中使用的 presence_of_element_located,表示判断某个元素是否被加载到了 HTML dom 树中。


expected_conditions 模块下也同样包含非常多的类,具体直接查看源码即可,传入的参数多数是一个元组类型的定位器( locator),格式为 (by,path),例如 (By.ID,'list-container'),其中 by 参数由 selenium.webdriver.common.by 模块提供。By 类提供的属性有


ID = "id"XPATH = "xpath"LINK_TEXT = "link text"PARTIAL_LINK_TEXT = "partial link text"NAME = "name"TAG_NAME = "tag name"CLASS_NAME = "class name"CSS_SELECTOR = "css selector"
复制代码

selenium 采集京东图书

接下来用学到的一点点内容,采集一下京东图书,整体代码如下所示,其中 get_attribute 方法用于获取 WebElement 对象的属性值。


from selenium import webdriverfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://book.jd.com/booktop/0-0-0.html?category=1713-0-0-0-10001-1#comfort") # 打开京东图书畅销榜locator = (By.XPATH, '//div[@class="mc"][1]/ul')try: ul = WebDriverWait(driver, 10).until(EC.presence_of_element_located(locator))except TimeoutError as te: print(te)
all_items = ul.find_elements_by_xpath('./li')for item in all_items: title = item.find_element_by_xpath('./div[2]/a').get_attribute('title') author = item.find_element_by_xpath('./div[3]/dl[1]/dd/a[1]').get_attribute('title') publisher = item.find_element_by_xpath('./div[3]/dl[2]/dd/a').text price = item.find_element_by_xpath('./div[3]/dl[3]/dd/del').text jd_price = item.find_element_by_xpath('./div[3]/dl[4]/dd/em').text print(title,author,publisher,price,jd_price)
driver.quit()
复制代码

订阅时间

今天是持续写作的第 <font color=red>276</font> / 365 天。可以<font color=#04a9f4>关注</font>我,<font color=#04a9f4>点赞</font>我、<font color=#04a9f4>评论</font>我、<font color=#04a9f4>收藏</font>我啦。


发布于: 刚刚阅读数: 3
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
用 python selenium 爬简书,Python自动化领域之 Selenium WebDriver 学习第2篇_3月日更_梦想橡皮擦_InfoQ写作平台