爬虫基础 --selenium库(解决JS渲染问题)

这篇博客介绍了如何利用Selenium库解决JavaScript渲染问题,包括声明浏览器与访问页面、导航、元素定位、异步等待以及异常处理。还提供了一个实例,展示了如何爬取淘宝美食页面。
部署运行你感兴趣的模型镜像

官方文档:http://selenium-python-docs-zh.readthedocs.io/zh_CN/latest/
模拟浏览器中网页的跳转,输入,点击,下拉
-安装:
pip install selenium
chromedriver : http://chromedriver.storage.googleapis.com/index.html
(谷歌若是最新版的就安装v2.36)

声明浏览器与访问页面

注:selenium支持很多浏览器,一般在测试阶段使用Chrome(需要下载Chromedriver,并配置环境变量);在运行阶段使用PhantomJS(需要配置环境变量),该浏览器可以无界面测试,网络截屏,页面自动化。

    from selenium import webdriver

    driver=webdriver.Chrome()   #声明浏览器对象
    driver.get("http://www.baidu.com") #通过浏览器打开百度页面
    print(driver.page_source) #得到网页html信息
    driver.close()  #关闭浏览器

导航

-页面交互(向文本框和文本域输入内容)
  #获取一个元素
  element=driver.find_element_by_id("pass_id")
  #通过send_keys方法输入文本信息
  element.send_keys("some text")
  #文本内容不会自动清除,因此避免干扰下次的操作需要清楚
  element.clear()

-填充表单(下拉选项框,并选中)
  #选中特定的选项---select方法
    from selenium.webdriver.support.ui import Select
    select = Select(driver.find_element_by_name('name'))
    select.selct_by_index(index)
    select.select_by_visible_text("text")
    select.select_by_value(value)
  #取消选中项--select.deselect_all方法
    select = Select(driver.find_element_by_id('id'))
    select.deselect_all()
  #提交表单 .click方法
    # 假设存在一个提交按钮的ID 为"submit" 
    driver.find_element_by_id("submit").click()

-拖拽(将一个元素拖拽指定的距离或到另一个元素上)
    #ActionChains方法
from selenium.webdriver import ActionChains

element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element,target).perform()    
-在窗口和框架间移动
    #将框架切换到另一个框架
        driver.switch_to_frame("frameName")
    #回到父框架
       driver.switch_to_default_content()

-弹出对话框
    #获取对话框元素
    alert=driver.switch_to_alert()

-Cookie
    # 进入一个网页页面
    driver.get("http://example.com")
    # 设置cookie字典键值对
    cookie = {'name':'foo','value':'bar'}
    #添加cookie到浏览器对象中
    driver.add_cookie(cookie)
    #得到浏览对象中的所有cookie值
    driver.get_cookies()

元素定位

#针对单个元素
    find_element_by_id #根据id定位
    find_element_by_name #根据name定位
    find_element_by_xpath #根据XPath定位
    find_element_by_link_text #根据用链接文本定位超链接
    find_element_by_tag_name #根据标签名(Tag name)定位
    find_element_by_class_name #根据class定位
    find_element_by_css_selector  #根据css选择器定位

#针对多个元素--返回一个list
    find_elements_by_name
    find_elements_by_xpath
    find_elements_by_link_text
    find_elements_by_tag_name
    find_elements_by_class_name
    find_elements_by_css_selector

#两个私有方法 find_element和find_elements
    from selenium.webdriver.common.by import By
    #driver是一个浏览器对象
    driver.find_element(By.XPATH,"//div[@class='section']//p/text()") 
----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"
#获取元素属性,文本值,ID,位置,标签名
    -element.get_attribute("attrs_name")
    -element.text
    -element.id
    -element.location
    -element.tag_name
    -element.size

注意:如果没有元素匹配,将会抛出NoSuchElementException

异步(等待,给页面的加载执行提供了一些时间间隔)

-显示等待
 #会让webdriver在更深一步的执行前等待一个确定的条件触发
 相对与time.sleep()等待的时间,显示等待则是让编写的代码只等待需要的时间(WebDriverWait结合ExpectedCondition实现)
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver=webdriver.Chrome()
driver.get("http://example.com")
try:
     element=WebDriverWait(driver,10).until(
     EC.presence_of_element_located((By.ID,"id_name"))
 )
finally:
    driver.quit()  
注意:
    触发条件(expected_conditions)
        title_is
        title_contains
        presence_of_element_located
        visibility_of_element_located
        visibility_of
        presence_of_all_elements_located
        text_to_be_present_in_element
        text_to_be_present_in_element_value
        frame_to_be_available_and_switch_to_it
        invisibility_of_element_located
        element_to_be_clickable  # it is Displayed and Enabled.
        staleness_of
        element_to_be_selected
        element_located_to_be_selected
        element_selection_state_to_be
        element_located_selection_state_to_be
        alert_is_present


-隐式等待
#会让webdriver试图定位元素的时候让DOM进行指定次数的轮询,默认设置是0次
from selenium import webdriver

driver=webdriver.Chrome()
driver.implicitly_wait(10) #单位是秒
driver.get("http://example.com")
myDynamicElement=driver.find_element_by_id("id_name")

异常处理

from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('Time Out')
try:
    browser.find_element_by_id('hello')
except NoSuchElementException:
    print('No Element')
finally:
    browser.close()

实例—爬去淘宝美食

import re
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from lxml import etree

driver=webdriver.Chrome() #建立浏览器对象
wait=WebDriverWait(driver,10) #创建显示wait对象


#搜索页面
def search():
    driver.get("https://www.taobao.com") 
    try:
        #获取文本框元素---注意触发条件的第一参数是一个元组
        input=wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, '#q'))
        )
        #获取提交按钮元素
        submit=wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_TSearchForm > div.search-button > button'))
        )

        #输入搜素关键字
        input.send_keys('美食')
        #点击提交
        submit.click()
        #获取底部总页面元素---主要是获取总共的页面数量
        total=wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.total'))
        )
        #解析第一页的html信息
        get_contents()
        return total.text
    except TimeoutException:
        return search()

#其他页信息判断
def next_page(page_number):
    try:
        #获取元素
        input = wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.form > input'))
        )
        submit = wait.until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit'))
        )
        #清楚文本框--必须要有
        input.clear()
        #输入页数
        input.send_keys(page_number)
        submit.click()
        #判断是否进入下一页---这里采用下一页的高亮按钮是否出现作为加载完成的判断依据
        wait.until(
            EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > ul > li.item.active'),str(page_number)))
        #获取该页的html信息
        get_contents()

    except TimeoutException:
        return next_page(page_number)

def get_contents():
    #加载判断条件
    wait.until(
        EC.presence_of_element_located((By.CSS_SELECTOR, '#main'))
    )
    html_str=driver.page_source
    html=etree.HTML(html_str)
    #分组
    div_list=html.xpath("//div[@data-category='auctions']")
    content_list=[]
    #迭代获取每一项
    for div in div_list:
        item = {}
        s=str(div.xpath(".//div[@class='pic']/a[@class='pic-link J_ClickStat J_ItemPicA']/img/@src"))
        item['img'] = "https:" +s
        content_list.append(item)

    print(content_list)

def main():
    total=search()
    total=int(re.compile('(\d+)').search(total).group(1))
    for i in range(2,total+1):
        next_page(i)

if __name__ == '__main__':
    main()


您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值