一、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()