requests
- requests模块:是对urllib的封装,可以实现urllib的所有功能
- 并且api调用更加简单方便
url, :要请求的目标url
params:get请求后面要拼接的参数
:param method: 要发起的是什么类型的请求.
:param url: 要请求的目标url
:param params: get请求后面要拼接的参数
:param data: Dictionary, post请求的表单数据
:param json: 传递json数据跟上面的data效果类似
:param headers: (optional) Dictionary 请求头
:param cookies: (optional) Dict or CookieJar object (设置cookies信息模拟用户请求)
:param files: 上传文件
:param auth: 网站需要验证的信息(账号和密码)
:param timeout: 设置请求的超时时间
:param allow_redirects: bool,是否允许重定向
:param proxies: (optional) Dictionary (设置代理)
:param verify: Defaults toTrue
.(忽略证书认证,默认为True表示不忽略)
- requests.session():维持会话,可以让我们在跨请求时保存某些参数
xpath
xpath:可以在xml中查找信息,对xml文档中元素进行遍历和属性的提取
xml:被设计的目的是为了传输数据,结构和html非常相识,是一种标记语言
xpath常见的语法:
nodename 选取此节点的所有子节点
/ 从根节点开始查找
// 匹配节点,不考虑节点的位置
. 选取当前节点
.. 选取当前节点的父节点
a/@href 取标签的数据
a/text() 取标签的文本
a[@class="123"] 根据class属性寻找标签
a[@id="123"] 根据id属性寻找标签
a[@id="123"][last()] 取最后一个id为123的a标签
a[@id="123"][postion() < 2] 取id为123的前两个a标签
pyquery
语法规则类似于Jquery,可以对html文本进行解析
q = PyQuery(html文档)
pq('css选择器')
items():获取到多个标签时,使用items()将PyQuery转换为一个生成器
然后在使用for in 循环
filter('css选择器'):过滤
text():获取标签的文本
attr('属性名')获取属性值
beautifulsoup
作用是从html/xml中提取数据,会载入整个HTML DOM,比lxml解析器效率要低
re
. :表示匹配除了换行符之外的任意字符
\ :转义字符
[a-z] : 匹配a-z里面的任意一个字符
\d: 匹配数字 -> [0-9]
\D: 匹配非数字 [^\d]
\s: 匹配空白字符(空格,\n,\t...)
\S: 匹配非空白字符
\w: 匹配单词字符 [A-Za-z0-9_]
\W: 匹配非单子字符
^:匹配以...开头
$:匹配以....结尾
():分组
|:或
- 多字符匹配
*:匹配*前面的字符任意次数
+: 匹配+号前面的字符至少1次
?: 匹配?前面的字符0次或1次
{m}:匹配{m}前面的字符m次
{m,n}:匹配{m,n}前面的字符m~n次
- 非贪婪匹配
*?
+?
??
{m,n}?
match 方法:从起始位置开始查找,一次匹配
search 方法:从任何位置开始查找,一次匹配
findall 方法:全部匹配,返回列表
finditer 方法:全部匹配,返回迭代器
split 方法:分割字符串,返回列表
sub 方法:替换
多线程
- threading.Thread参数介绍
target:线程执行的函数
name:线程名称
args:执行函数中需要传递的参数,元组类型 另外:注意daemon参数
如果某个子线程的daemon属性为False,主线程结束时会检测该子线程是否结束,如果该子线程还在运行,则主线程会等待它完成后再退出;
如果某个子线程的daemon属性为True,主线程运行结束时不对这个子线程进行检查而直接退出,同时所有daemon值为True的子线程将随主线程一起结束,而不论是否运行完成。
属性daemon的值默认为False,如果需要修改,必须在调用start()方法启动线程之前进行设置
互斥锁
当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。
互斥锁为资源引入一个状态:锁定/非锁定
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
threading模块中定义了Lock类,可以方便的处理锁定:
创建锁
mutex = threading.Lock()
锁定
mutex.acquire()
释放
mutex.release()
锁的好处:
确保了某段关键代码只能由一个线程从头到尾完整地执行
锁的坏处:
阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁
死锁问题
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
尽管死锁很少发生,但一旦发生就会造成应用的停止响应
多进程
进程:一个程序运行起来后,代码+用到的资源 称之为进程,它是操作系统分配资源的基本单元。
不仅可以通过线程完成多任务,进程也是可以的
multiprocessing模块就是跨平台版本的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情
Queue的使用
Queue本身是一个消息列队程序
Queue.qsize():返回当前队列包含的消息数量;
Queue.empty():如果队列为空,返回True,反之False ;
Queue.full():如果队列满了,返回True,反之False;
Queue.get(block, timeout):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;
1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果为空,此时程序将被阻塞(停在读取状态),直到从消息列队读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出"Queue.Empty"异常;
2)如果block值为False,消息列队如果为空,则会立刻抛出"Queue.Empty"异常;
Queue.get_nowait():相当Queue.get(False);
Queue.put(item,block,timeout):将item消息写入队列,block默认值为True;
1)如果block使用默认值,且没有设置timeout(单位秒),消息列队如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息列队腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出"Queue.Full"异常;
2)如果block值为False,消息列队如果没有空间可写入,则会立刻抛出"Queue.Full"异常;
Queue.put_nowait(item):相当Queue.put(item, False);
- Queue实例以及在多进程间的使用
multiprocessing.Pool常用函数解析:
apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
close():关闭Pool,使其不再接受新的任务;
terminate():不管任务是否完成,立即终止;
join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;
进程与线程的对比
进程、线程对比 功能
进程,能够完成多任务,比如 在一台电脑上能够同时运行多个QQ
线程,能够完成多任务,比如 一个QQ中的多个聊天窗口
定义的不同
进程是系统进行资源分配基本单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.
线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享所在进程所拥有的全部资源
区别
一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
线线程不能够独立执行,必须依存在进程中
优缺点
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。
使用场景:
多进程常用来处理计算密集型任务: 计算密集型任务的特点:是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。计算密集型任务可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。
多线程常用来处理IO密集型任务: IO密集型:涉及到网络、磁盘IO的任务都是IO密集型任务,特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。但是也要切记,在执行多任务时,并不是越多线程越好。
SELENIUM
Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器)。 Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。
Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行,所以我们可以用一个叫 PhantomJS 的工具代替真实的浏览器。
主要使用的方法和代码如下
from selenium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException,TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
# 要想调用键盘按键操作需要引入keys包
from selenium.webdriver.common.keys import Keys
# 加载网页(使用火狐浏览器加载)
# driver = webdriver.Firefox(executable_path='/home/ljh/桌面/driver/geckodriver')
# driver.get('https://www.baidu.com/')
# 加载网页(使用无头浏览器加载)
# driver = webdriver.PhantomJS(executable_path='/home/ljh/桌面/driver/phantomjs')
# driver.get('https://www.baidu.com/')
# 加载网页(使用谷歌浏览器加载)
# 创建chrome参数对象
# opt = webdriver.ChromeOptions()
# 把chrome设置成为无界面模式
# opt.set_headless()
# driver = webdriver.Chrome(
options=opt, executable_path='/Users/ljh/Desktop/chromedriver'
)
driver = webdriver.Chrome(executable_path='/home/ljh/桌面/driver/chromedriver')
#设置页面的加载超时时间
driver.set_page_load_timeout(0.1)
#处理异常
try:
driver.get('https://www.baidu.com/')
driver.save_screenshot('prcture.png')
except TimeoutException as err:
print(err)
#定位和操作
# driver.find_element_by_xpath():根据xpath定位节点
# driver.find_element_by_class_name():根据类名定位节点
# driver.find_element_by_partial_link_text():根据部分文本内容定位节点
# driver.find_element_by_css_selector():根据css选择器定位节点
# driver.find_element_by_link_text():根据完整文本定位节点
driver.find_element_by_id('kw').send_keys('隔壁老赵')
driver.find_element_by_id('su').click()
#获取信息
print(len(driver.page_source))
print(driver.get_cookies())
print(driver.current_url)
print(driver.name)
#清空输入框内容
driver.find_element_by_id('kw').clear()
#输入框重新输入内容
driver.find_element_by_id('kw').send_keys('风景')
#模拟回车键
driver.find_element_by_id('su').send_keys(Keys.RETURN)
#获取当前的url
#截取网页页面(生成当前的页面快照并保存)
driver.save_screenshot('baidu.png')
#前进和后退
time.sleep(2)
driver.back() #后退
time.sleep(2)
driver.forward() #前进
#获取属性和获取文本
time.sleep(2)
href = driver.find_element_by_xpath('//h3[@class="t"]/a').get_attribute('href')
title = driver.find_element_by_xpath('//h3[@class="t"]/a').text
print(href)
print(title)
#关于cookie相关操作
cookies_dict = {cookie['name']:cookie['value'] for cookie in driver.get_cookies()}
print(cookies_dict)
print(driver.get_cookie('BIDUPSID'))
# driver.delete_all_cookies()
# driver.delete_cookie()
# driver.add_cookie()
###页面等待
# 因为selenium加载的页面和浏览器一样会渲染页面,并且有些网页加载需要消耗时间
# 这时在页面加载出来之前去寻找节点的话,会报异常,所有我们需要添加等待,有时甚至
# 需要前置等待
# 强制等待
# time.sleep(5)
# 隐士等待(设置等待时间)
# driver.implicitly_wait(10)
# 是指显示等待:设置最大的等待时间
# 直到某一条件成立然后继续执行
# WebDriverWait(driver,10).until(EC.presence_of_element_located(By.ID,''))
#退出
driver.close() #退出当前页面
driver.quit() #退出浏览器
页面的相关操作
Selenium 的 WebDriver提供了各种方法来寻找元素,假设下面有一个表单输入框如
element = driver.find_element_by_id("passwd-id")
获取name标签值
element = driver.find_element_by_name("user-name")
获取标签名值
element = driver.find_elements_by_tag_name("input")
也可以通过XPath来匹配
element = driver.find_element_by_xpath("//input[@id='passwd-id']")
页面前进和后退
driver.forward() #前进
driver.back() # 后退
Cookies操作
cookies = driver.get_cookies()
cookie_dict = {i['name']:i['value'] for i in cookies}
Selenium 提供了两种等待方式,一种是隐式等待,一种是显式等待。
隐式等待是等待特定的时间,如果节点没有立即出现,隐士等待将一段时间再进行查找 显式等待是指定一个最长的等待时间,直到条件成立时继续执行。如果在设定时间内没加载出来节点,则返回异常信息,如果加载出来了则返回节点
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://www.xxxxx.com/loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")
显式等待指定某个条件,然后设置最长等待时间。如果在这个时间还没有找到元素,那么便会抛出异常了。
from selenium import webdriver
from selenium.webdriver.common.by import By
# WebDriverWait 库,负责循环等待
from selenium.webdriver.support.ui import WebDriverWait
# expected_conditions 类,负责条件出发
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("http://www.xxxxx.com/loading")
try:
##### 会在这里等待,如果10秒内 id="myDynamicElement"的标签出现
则返回,如果不出现则报异常
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located(
(By.ID, "myDynamicElement")
)
)
finally:
driver.quit()
异常处理
- 请求超时异常处理
from selenium.common.exceptions import TimeoutException
try:
brower.get(url)
except TimeoutException:
print('Time out')
- 找不到标签的异常处理
from selenium.common.exceptions import NoSuchElementException
try:
brower.find_element_by_id('').click()
print('有标签')
except NoSuchElementException:
print('没有这个标签')