zoukankan      html  css  js  c++  java
  • 爬虫之xpath、selenuim

    一、Xpath

    注意:xpath中不能出现tbody标签,可以用 // 来跳过这个标签

    1、简单使用对象实例化:

    from lxml import etree
    #
    本地文件: tree = etree.parse('文件名') tree.xpath('xpath表达式') #网络数据: tree = etree.HTML(网页内容字符串) tree.xpath('xpath表达式')

    2、常用的方法:

    (1)属性定位:

    #找到class属性值为song的div标签
    tree.xpath('//div[@class="song"]') 

    (2) 层级&索引定位:

    #找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a
    tree.xpath('//div[@class="tang"]/ul/li[2]/a')

    (3) 逻辑运算

    #找到href属性值为空且class属性值为du的a标签
    tree.xpath(' //a[@href="" and @class="du"]’)

    (4)模糊匹配

    #找以class属性值中有ng的div
    tree.xpath('//div[contains(@class, "ng")]')
    # 找以class属性值为ta开头的div
    tree.xpath(' //div[starts-with(@class, "ta")]')

    (5)取文本

    # /表示获取当前标签下的文本内容         
      //div[@class="song"]/p[1]/text()
    # //表示获取当前标签下的文本内容和所有子标签下的文本内容    
     //div[@class="tang"]//text()

    (6)获取属性值

    # 7 属性获取  @href 取当前标签的属性
    etree.xpath('//body//a/@href')

    (7)其他方法:

    # # 注意从1 开始取(不是从0)
     a=html.xpath('//body//a[1]/@href')
    #  属性多值匹配
    #  a 标签有多个class类,直接匹配就不可以了,需要用contains
     a=html.xpath('//body//a[@class="li"]')
     a=html.xpath('//body//a[contains(@class,"li")]')
     a=html.xpath('//body//a[contains(@class,"li")]/text()')
    #  多属性匹配
     a=html.xpath('//body//a[contains(@class,"li") or @name="items"]')
     a=html.xpath('//body//a[contains(@class,"li") and @name="items"]/text()')
     a=html.xpath('//body//a[contains(@class,"li")]/text()')
    #  按序选择
     a=html.xpath('//a[2]/text()')
     a=html.xpath('//a[2]/@href')
    # 取最后一个
     a=html.xpath('//a[last()]/@href')
    # 位置小于3的
     a=html.xpath('//a[position()<3]/@href')
    # 倒数第二个
     a=html.xpath('//a[last()-2]/@href')
    #  节点轴选择
    # ancestor:祖先节点
    # 使用了* 获取所有祖先节点
     a=html.xpath('//a/ancestor::*')
    # # 获取祖先节点中的div
     a=html.xpath('//a/ancestor::div')
    # attribute:属性值
     a=html.xpath('//a[1]/attribute::*')
     a=html.xpath('//a[1]/@aa')
    # child:直接子节点
     a=html.xpath('//a[1]/child::*')
     a=html.xpath('//a[1]/child::img/@src')
    # descendant:所有子孙节点
     a=html.xpath('//a[6]/descendant::*')
     a=html.xpath('//a[6]/descendant::h5/text()')
    # following:当前节点之后所有节点(兄弟节点和兄弟内部的节点)
     a=html.xpath('//a[1]/following::*')
     a=html.xpath('//a[1]/following::*[1]/@href')
    # following-sibling:当前节点之后同级节点(只找兄弟)
     a=html.xpath('//a[1]/following-sibling::*')
     a=html.xpath('//a[1]/following-sibling::a')
     a=html.xpath('//a[1]/following-sibling::*[2]')
     a=html.xpath('//a[1]/following-sibling::*[2]/@href')

    二、selenium

    1、环境安装

    # 下载安装selenium模块
    pip install selenium
    
    # 下载对应的浏览器版本驱动程序:chromdriver
    国内镜像网站地址:http://npm.taobao.org/mirrors/chromedriver/2.38/

    2、简单使用

     from selenium import webdriver
     import time
     # bro=webdriver.Chrome()  # 得到一个谷歌浏览器对象,
     # 指定使用跟那个驱动
     bro=webdriver.Chrome(executable_path='./chromedriver.exe') # 得到一个谷歌浏览器对象,
     time.sleep(2)
     bro.get('https://www.baidu.com/')  # 在地址栏里输入了百度
     time.sleep(2)
     # 获取网页内容
     print(bro.page_source)
     time.sleep(2)
     # 关闭浏览器
     bro.close()

    3、标签定位:find系列

    '''
    - id定位:find_element/elements_by_id()
    - name定位:find_element_by_name()
    - class定位:find_element_by_class_name()
    - tag定位:find_element_by_tag_name()
    - link(文本链接)定位:find_element_by_link_text()
    - partial_link(模糊匹配)定位:find_element_by_partial_link_text()
    - xpath定位:find_element_by_xpath()
    - css定位:find_element_by_css-selector()
    
    注意:element查找的是第一符合条件的标签
             elements是查找所有符合条件的标签
    '''
    #===============示范用法===================
    # 1、find_element_by_id
    print(driver.find_element_by_id('kw'))
    
    # 2、find_element_by_link_text
    # login=driver.find_element_by_link_text('登录')
    # login.click()
    
    # 3、find_element_by_partial_link_text
    login=driver.find_elements_by_partial_link_text('')[0]
    login.click()
    
    # 4、find_element_by_tag_name
    print(driver.find_element_by_tag_name('a'))
    
    # 5、find_element_by_class_name
    button=wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'tang-pass-footerBarULogin')))
    button.click()
    
    # 6、find_element_by_name
    input_user=wait.until(EC.presence_of_element_located((By.NAME,'userName')))
    input_pwd=wait.until(EC.presence_of_element_located((By.NAME,'password')))
    commit=wait.until(EC.element_to_be_clickable((By.ID,'TANGRAM__PSP_10__submit')))
    
    input_user.send_keys('18611453110')
    input_pwd.send_keys('xxxxxx')
    commit.click()
    
    # 7、find_element_by_css_selector
    driver.find_element_by_css_selector('#kw')
    
    # 8、find_element_by_xpath
    ```
        time.sleep(5)
    
    finally:
        driver.close()

    4、标签交互

    '''
    clear():清空输入框内容
    send_keys(keyword):输入一个关键词keyword
    click():点击事件,强调事件的独立
    submit(): 用于对信息的提交,提交对象是一个表单
    '''
    
    # =====例子=====
    # 点击
    button=browser.find_element_by_css_selector('#nav-search > form > div.nav-right > div > input')
    button.click()
    # 清空
    input_tag=browser.find_element_by_id('twotabsearchtextbox')
    input_tag.clear() #清空输入框
    # 输入
    input_tag.send_keys('iphone7plus')

    5、获取标签属性

    tag=browser.find_element(By.CSS_SELECTOR,'#cc-lm-tcgShowImgContainer img')
    
    #获取标签属性,
    print(tag.get_attribute('src'))
    
    #获取标签ID,位置,名称,大小(了解)
    print(tag.id)
    print(tag.location)
    print(tag.tag_name)
    print(tag.size)

    6、执行js程序

    execute_script(js代码)
    #例子:
    bro.execute_script('window.scrollTo(0, document.body.scrollHeight)')
    bro.execute_script('alert("123")')

    7、其他方法:

    '''
    # 获取页面源码数据的方法
    page_source
    # 前进和后退的方法
    forward() #前进
    back() # 后退
    # Cookie处理方法
    get_cookies() # 获取cookie
    add_cooki() #添加cooki
    delete_all_cookies() # 删除cookies
    '''
    # ====案例====
    # 模拟浏览器前进后退
    import time
    from selenium import webdriver
    browser=webdriver.Chrome()
    browser.get('https://www.baidu.com')
    browser.get('https://www.taobao.com')
    browser.get('http://www.sina.com.cn/')
    browser.back()
    time.sleep(10)
    #获取页面源码数据
    browser.page_source()
    browser.forward()
    
    # cookies的例子
    browser=webdriver.Chrome()
    browser.get('https://www.zhihu.com/explore')
    # 获取cookie值
    print(browser.get_cookies())
    # 添加cookies browser.add_cookie({
    'k1':'xxx','k2':'yyy'}) print(browser.get_cookies()) # browser.delete_all_cookies()

    8、无界面操作

    ####无界面浏览器(phantomjs)
    #谷歌浏览器支持不打开页面
     from selenium.webdriver.chrome.options import Options
     from selenium import webdriver
     chrome_options = Options()
    
     chrome_options.add_argument('window-size=1920x3000') #指定浏览器分辨率
     chrome_options.add_argument('--disable-gpu') #谷歌文档提到需要加上这个属性来规避bug
     chrome_options.add_argument('--hide-scrollbars') #隐藏滚动条, 应对一些特殊页面
     chrome_options.add_argument('blink-settings=imagesEnabled=false') #不加载图片, 提升速度
     chrome_options.add_argument('--headless') #浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
    #
    bro=webdriver.Chrome(chrome_options=chrome_options,executable_path='./chromedriver.exe')
     bro.get('https://www.baidu.com/')
    # 窗口全屏
    bro.maximize_window()
     print(bro.page_source)
     bro.close()

    9、动作链

    #1、导入库
    from selenium.webdriver import ActionChains
    # 实例化一个动作链对象:
    action=AcitonChains(浏览器对象名字)
    '''
    方法:click_and_hold(div) #长按且点击操作
            move_by_offset(x,y) # 移动
    注意:要调用这个方法:perform(),否则该对象不会执行
             如果定位的标签存在iframe标签,则必须使用switch_to.frame(id)
    '''
    # 例子:
    #frame相当于一个单独的网页,在父frame里是无法直接查看到子frame的元素的,必须switch_to_frame切到该frame下,才能进一步查找
    
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
    
    try:
        browser=webdriver.Chrome()
        browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
    ```
    browser.switch_to.frame('iframeResult') #切换到id为iframeResult的frame
    
    ```
        tag1=browser.find_element_by_id('droppable')
        print(tag1)
    ```
    # tag2=browser.find_element_by_id('textareaCode') #报错,在子frame里无法查看到父frame的元素
    browser.switch_to.parent_frame() #切回父frame,就可以查找到了
    tag2=browser.find_element_by_id('textareaCode')
    print(tag2)
    ```
    finally:
        browser.close()

    10、显隐式等待

    #1、selenium只是模拟浏览器的行为,而浏览器解析页面是需要时间的(执行css,js),一些元素可能需要过一段时间才能加载出来,为了保证能查找到元素,必须等待
    
    #2、等待的方式分两种:
    隐式等待:在browser.get('xxx')前就设置,针对所有元素有效
    显式等待:在browser.get('xxx')之后设置,只针对某个元素有效
    
    # 案例
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
    from selenium.webdriver.common.keys import Keys #键盘按键操作
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
    
    browser=webdriver.Chrome()
    
    #隐式等待:在查找所有元素时,如果尚未被加载,则等10秒
    browser.implicitly_wait(10)
    
    browser.get('https://www.baidu.com')
    
    #显式等待:显式地等待某个元素被加载
    wait=WebDriverWait(browser,10)
    wait.until(EC.presence_of_element_located((By.ID,'content_left')))
    
    input_tag=browser.find_element_by_id('kw')
    input_tag.send_keys('美女')
    input_tag.send_keys(Keys.ENTER)
    
    contents=browser.find_element_by_id('content_left') #没有等待环节而直接查找,找不到则会报错
    print(contents)
    
    browser.close()

     模拟登陆案例

    # -*-coding:utf-8 -*-
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    from selenium.webdriver.chrome.options import Options
    import time
    from chaojiying import Chaojiying_Client
    from PIL import Image
    
    chrome_options = Options()
    chrome_options.add_argument('window-size=1920x3000')
    bro = webdriver.Chrome(executable_path='./chromedriver.exe', chrome_options=chrome_options)
    bro.get('https://www.12306.cn/index/')
    time.sleep(1)
    # 窗口最大化
    bro.maximize_window()
    time.sleep(2)
    login_button = bro.find_element_by_xpath('//*[@id="J-header-login"]/a[1]')
    login_button.click()
    time.sleep(3)
    #账号密码登陆
    button = bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a')
    button.click()
    time.sleep(2)
    bro.get_screenshot_as_file('web.png')
    
    user_input = bro.find_element_by_id('J-userName')
    user_input.send_keys('13927037099')
    time.sleep(1)
    passwd_input = bro.find_element_by_id('J-password')
    passwd_input.send_keys('123456789')
    code_tag = bro.find_element_by_id('J-loginImg')
    # 验证码图片大小
    code_img_site = code_tag.size
    # 验证码图片位置
    code_img_w = code_tag.location
    x = int(code_img_w['x']) * 1.25
    y = int(code_img_w['y']) * 1.25
    height = int(code_img_site['height']) * 1.25
    width = int(code_img_site['width']) * 1.25
    # 因为我们桌面是125%显示
    img_tu = (x, y, x + width, y + height)
    img = Image.open('./web.png')
    code_img = img.crop(img_tu)
    code_img.save('code_img.png')
    #调用超级鹰识别验证码
    chaojiying=Chaojiying_Client('账号','密码','    应用id')
    im=open('./code_img.png','rb').read()
    result=chaojiying.PostPic(im,9004)
    # 多个结果" 219,102 | 222,111
    all_list=[]
    if '|' in result['pic_str']:
        pic_list=result['pic_str'].split('|')
        for li in pic_list:
            x_y_list=li.split(',')
            l=[x_y_list[0],x_y_list[1]]
            all_list.append(l)
    else:
        x_y_list=result['pic_str'].split(',')
        l = [x_y_list[0], x_y_list[1]]
        all_list.append(l)
    #动作链
    # 注意x,y要进行缩放,不然会发生点击偏移
    for post in all_list:
        x=int(post[0])/1.25
        print(x)
        y=int(post[1])/1.25
        print(y)
        ActionChains(bro).move_to_element_with_offset(code_tag,x,y).click().perform()
        time.sleep(1)
    bro.find_element_by_xpath('//*[@id="J-login"]').click()
    bro.close()
  • 相关阅读:
    css换行
    <a>标签里的<img>标签点击虚线框
    iframe子页面调用父页面元素
    快捷键
    用css绘制三角形
    解决div被embed,object覆盖问题
    一些兼容问题
    兼容padding
    记一次用html2canvas将页面内容生成海报并保存图片到本地
    PUPPETEER安装遇到 ERROR:CHROMIUM REVISION IS NOT DOWNLOADED.的解决办法
  • 原文地址:https://www.cnblogs.com/nq31/p/14157599.html
Copyright © 2011-2022 走看看