很多文字内容都是通过自己的理解写的,如果有理解不到位的地方,还望指正.
selenium部分是通过看资料整理的,很多东西不是很懂,有待进一步学习.
一. requests 模块
基于urllib的模块 , 用法比urllib简单
1. requests的方法
requests.get(url,params=None)
用get方法获取请求 得到响应
参数:
url 要请求的地址
params 请求地址要传的参数 以字典形式给出
比如: dic = {'name':"Tom",'age':18}
requests.get(url,params=data)
传参也可以直接在url中拼接参数(仅限get请求) 如: 'http://www.baidu.com?name=tom&age=18/'
其他请求方式:
requests.post() --- post put delete .....
2. requests.get(url) 得到的响应的 属性 及 处理
response = requests.get(url)
得到响应对象的一些属性
html = response.text
--- 该url的html字符串
有些网站可能是以json格式返回,用txt属性得到的仍然是 字符串(字典形式的字符串)
这里可以用json.loads(html)方法处理, --- 就可以得到 字典格式的数据
更方便的方法 直接用 response.json() 这个方法获得的就是 字典格式的数据
这个方法的实质就是,在函数内部,对 response.txt 获得的内容 进行了 json.loads() 处理
response.status_code -- 状态码 200+ 300+ 400+ 500+
response.cookies -- 得到cookie 对象 <class 'requests.cookies.RequestsCookieJar'>
response.headers -- 响应头 返回一个字典
response.url -- 返回网址url
response.history -- 访问历史 返回一个列表 没有 历史就返回空列表
....
...
获取二进制信息
response.content
可以读取图片 视频等信息 用于保存
比如:
response = requests.get(url)
with open('tu.jpg','wb') as f:
f.write(response.content)
requests的高级操作:
上传文件:
files = {'file':open('文件路径','rb')}
response = requests.post(url,files=files)
post方式上传文件
模拟会话:
requests.get('http://httpbin.org/cookies/set/number/123456789')
res = requests.get('http://httpbin.org/cookies')
res.cookies
以上操作获取不到cookies.
因为 两次get请求相当于模拟了两个不同的浏览器请求,
第一个浏览器设置了cookies,但在另一个浏览器再次请求 肯定获取不到cookies
# 先创建一个session对象, 然后用session对象访问时 , 设置cookies,
# 再次用这个session对象访问时,相当于在同一浏览器发起的访问,这样就可以获取cookies
s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456789')
res = s.get('http://httpbin.org/cookies')
以上操作可以获取到cookies,相当于在同一浏览器对url进行了访问
因此,用session对象对url进行post登录访问,访问成功后,已经保存了cookies
再次使用该对象对url进行get访问 可以成功访问登录后的主页
相当于在一个浏览器操作,实现了模拟会话
证书验证:
requests.get(url) # https...的url
用这个方法访问https协议的url网站,会首先验证 网站证书
如果网站证书不是正版授权的,会报出SSLError错误 --- 比如 https://12306.cn
避免这种报错:
只需要请求时加一个参数: verify=是否进行证书验证
requests.get('https://12306.cn',verify=False)
不会产生报错,会提示一个警告信息
补充: 不显示警告信息
---- from requests.packages import urllib3
urllib3.disable_warnings() 不显示警告信息
--- 还可以手动指定证书 本地证书
requests.get('https://www.12306',cert=('/path/server.crt','/path/key'))
代理设置:
设置代理的网址ip+port:
proxies = {
'https':'https://127.0.0.1:9999',
'http':'http://127.0.0.1:9999',
}
直接把参数传进去,就可以通过代理访问网址
res = requests.get('https://www.taobao.com',proxies=proxies)
---
如果代理是私密代理,用用户名和密码时,
proxies = {
'https':'http://user:password@ip:port'
}
***
有些代理不是http/https代理 可能是 socks5 代理
这里需要安装模块 pip3 install 'requests[socks]'
不需要导入 直接用requests使用
proxies = {
'http':'socks5://ip:port'
'https':'socks5://ip:port'
}
下面同上 直接传入proxies参数即可
超时设置:
传入参数 timeout = 1 单位 s
认证设置:
有些网站在你访问的时候, 直接就会让你输入用户名和密码,如果没有就会返回401
两种方式处理:
一:
from requests.auth import HTTPBasicAuth
res = requests.get(url,auth=HTTPBasicAuth('user','123'))
二:
直接传参 传一个字典
res = requests.get(url,auth=('user','123'))
异常处理:
from requests.exceptions import ReadTimeout,ConnectionError,RequestException
二.
正则表达式
import re
result = re.match(pattern,content,匹配模式) # 返回一个对象
result.group() # 不加任何参数 可获得完整的匹配内容
result.group(1) # 获取正则里第一个子组匹配到的内容
match匹配 必须从第一个字符匹配,如果第一个字符不匹配,就直接返回None
re.search 扫描整个字符串并返回第一个成功的匹配,只返回一个
re.search(pattern,content)
这里pattern一般用一个正则匹配对象,
通过 pattern = re.complie('正则',匹配模式) 获得
这个方法 将正则字符串编译成正则表达式对象,以便于复用该匹配模式
匹配模式 re.S -- 让点 . 可以匹配到换行符\n
re.findall(pattern,content)
搜索字符串,以 列表形式 返回全部能匹配到的 子串(就是正则表达式中括号中的内容)
re.sub(pattern,str,content)
把用正则pattern 在content中匹配到的内容,用str替换掉,最后返回替换后的字符串
re.sub('***(**)**',r'\1 123') 这里的 \1 代表的是 正则中 括号里匹配到的内容
-- '** 123' 这是最终要替换进去的内容
BeautifulSoup
install beautifulsoup4
from bs4 import BeautifulSoup
soup = BeautifulSoup(html,'lxml')
参数: html -- 网页源码字符串
lxml -- 解析器 (其他解析器 'html.parser' / 'xml' / 'html5lib')
返回一个对象,
这个对象的方法/属性
soup.prettify() 把html网页字符串 格式化, 使字符串更美观,便于观察
soup.标签名.string 获得该标签对应的 内容
标签选择器
soup.标签名 --比如 soup.title
返回 一个标签对象 -- 比如 <title>*******</title>
如果有多个该标签,只会返回第一个匹配到的
获取名称
soup.title.name --- 返回: title
获取属性:
soup.p.attrs['属性名'] -- 得到属性值
soup.p['属性名'] -- 同上
获取内容:
soup.p.string -- 得到 匹配到的 p 标签里的内容
嵌套选择:
获取到标签对象之后 还可以继续获取该标签内的 子标签的内容
soup.head.title.string
字节点 和 子孙节点
soup.标签名.contents -- 返回一个列表,列表中每个元素是该标签的所有子标签的字符串
soup.标签名.children
-- 返回一个迭代器对象, 可用循环取到内容
补充: for i,child in enumerate(soup.p.children): 枚举遍历
返回的 i 是索引下标值
child 是子节点的内容(包括文本节点)
soup.标签名.descendants
返回所有的子孙节点 (换行符 和 每个标签中的文本内容 也会被单独输出)
返回的是一个生成器,可循环遍历
父节点 和 祖先节点
soup.a.parent 首先匹配到第一个a标签,然后再匹配到该a节点的父节点
soup.a.parents 匹配到第一个a元素的所有祖先节点 返回的是一个可迭代对象 可遍历得到结果
兄弟节点
soup.a.next_siblings 获取后面的所有的兄弟节点
soup.a.previous_siblings 获取前面的所有的兄弟节点
提供的一些API 标准选择器
find_all()
根据标签名,属性,内容查找
把匹配到的结果,以列表的形式返回,
列表中的每个元素是 标签对象 (与soup.标签名 返回的类型是一样的,因此,这个对象可以使用标签对象的所有方法)
soup.find_all('标签名') -- 根据标签名查找
soup.find_all(attrs={'属性名':'属性值',...}) -- 根据属性 查找
soup.find_all(id='属性值') -- 查找id为该属性值的对象
由于 class 是python中的关键字 ,根据class属性查的时候 用 class_='属性值' 查找
soup.find_all(text='Foo') 返回['Foo','Foo'] 返回的仅仅是内容 的列表
find()
返回匹配结果的第一个元素对象,不是一个列表
查找不存在的标签,则会返回一个None
CSS选择器
通过select() 直接传入CSS选择器即可完成选择
类选择器 -- 前面加点 .
元素选择器 -- 直接写元素名
id选择器 -- 前面加 # 号
选择器以一个字符串的方式给出 选择器之间用空格隔开 : soup.select(".class #id p")
多个选择器之间可以使层层嵌套的关系
可能匹配到多个标签,,因此返回的是一个列表,列表中的元素是 便签对象
由于是列表所以可以用 [] 索引取下标的 方法得到每个元素
获取属性:
获得 标签对象 之后,通过标签对象获取属性
标签对象['属性名'] or 标签对象.attrs['属性名']
获取文本:
标签对象.get_text()
总结:
1. 建议使用 lxml 解析库 必要时使用 html.parser
2. 建议使用 find() find_all()
3. 建议使用CSS选择器
4. 记住常用的获取属性和文本值的方法
PyQuery
与jquery 无缝衔接, API接口 完全相同
from pyquery import PyQuery as pq
1) 字符串初始化
html=''
doc = pq(html)
-> pq对象
doc('标签名')
URL初始化
doc = pq(url='http://www.baidu.com')
doc('标签名')
文件初始化
doc = pq(filename='路径文件名')
doc('标签名')
2) 基本CSS选择器
doc('#id .class li') 选择器之间空格隔开 不一定是父子关系
3) 查找元素
items= doc('选择器') - > pyquery 对象
查找子元素
items.find('标签名') -> 返回的仍然是pyquery对象,仍然可以继续使用find方法
find(查找子孙元素中 所有符合条件的)
items.children('选择器')
查找子元素中 符合条件的元素
父元素
items.parent() -> 返回的仍然是pyquery对象
返回整个父元素的内容
items.parents() ->
返回所有的祖先节点元素
parents('选择器') -> 在所有祖先元素中再次进行筛选
兄弟元素
items = doc('选择器1 选择器2选择器3')
可以看到选择器2和3之间没有空格,表示的是并列关系,
空格隔开表示的是嵌套关系
items.siblings()
返回所有的兄弟元素,这些兄弟元素也可以继续通过选择器进行筛选
遍历:
doc('选择器').items()
->可得到一个生成器,从中可以获取用选择器匹配到的元素
4) 获取属性/文本
a = doc('选择器')
a.attr('属性名') 方法 --- a.attr.href 属性
两种方式 都可以获得属性值
a.text() --- 获取文本内容(如果有子节点,子节点中的文本也会被获取)
a.html() 获取标签里的html内容 -- 类似 jquery
5) DOM操作 - 动态修改节点内容
各种api
a = doc('选择器')
a.removeClass('类名字') 在类属性中删除该类
a.addClass('类名字') 在该元素中 添加类
属性操作:
a.attr('name','link') -- 添加/修改 name属性的值
添加/修改其他属性也一样
a.css('font-size','14px')
-- 添加/设置css,也就是style属性
a.find('选择器').remove() 把找到的元素从a这个pyquery对象中删除
6) 伪类选择器
doc('li:first-child')
doc('li:last-child')
doc('li:nth-child(2)')
doc('li:gt(2)')
doc('li:nth-child(2n)') # 第偶数个
doc('li:contains(second)')
Selenium
自动化测试工具,支持多种浏览器,
爬虫中主要解决JavaScript渲染的问题
基本用法:
1) 声明一个浏览器对象
引入一个 webdriver 包
from selenium import webdriver
browser = webdriver.Chrome() 创建一个 weddriver 对象,
browser.page_source 获得网页内容
单个元素 find_element
多个元素 find_elements
2) 通过webdriver对象 获取单个元素
browser.find_element_by_id('id值') # 获取该元素,返回是一个WebElement对象
browser.find_element_by_css_selector('#q') 通过css选择器获取元素
browser.find_element_by_xpath('xpath路径') 通过xpath路径获取元素
....by_name() 通过元素名
...by_link_text()
...by_partial_link_text()
...by_tag_name()
...by_class_name()
通用的查找方式:
from selenium.webdriver.common.by import By
browser.find_element(By.ID,'q')
通用的查找方式,
By.ID -- 表示通过ID属性方式查找,还有其他的
By.CSS_SELECTOR 选择器
3) 查找多个元素
与单个元素的区别
find_elements 复数形式
返回的是一个列表,列表中每个元素是 WebElement对象
4) 元素交互操作
对获取的元素调用交互的方法
input = browser.find_element_by_id('一个输入框的ID')
input.send_keys('关键字') # 相当于在文本框中输入iphone
input.clear() # 清空文本框
然后获取搜索按钮 button
button.click() # 相当于点击了按钮
5) 交互动作
拖拽,双击等动作
导入一个模块
from selenium.webdriver import ActionChains
broeser = webdriver.Chrome()
先获取两个元素: 要移动的元素source 目标元素target
再获取 ActionChains 对象
actions = ActionChains(browser)
actions.drag_and_drop(source,target)
actions.perform() # 执行以上动作
其他的 交互动作 可查官方文档API
6) 执行 JavaScript
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
把下拉框拉到最下面
7) 获取元素信息
获取属性
元素对象.get_attribute('class') 获取class属性
元素对象.text 文本值
元素对象.id id
标签对象.location 元素在网页中的位置{'y':7,'x':774}
元素对象.tag_name 标签名
元素对象.size 元素的大小 ('height':32,'width':66)
8) 等待
为防止因为网页加载慢,而获取不到元素的问题,通常需要等待
隐式等待
当使用了隐式等待执行的时候,如果webdriver没有在DOM中找到元素,
将继续等待,超出设定时间后,将抛出异常.
换句话说,当查找元素或者元素没有立即出现的时候,隐式等待将等待一段时间,再继续查找DOM,默认时间为0
browser.implicitly_wait(10)
browser.get(url)
...
显式等待 -- 常用
from selenium.weddriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser.get(url)
wait = WebDriverWait(browser,10) # 创建一个wait对象,关联browser,最长等待时间是10s
input = wait.until(EC.presence_of_element_located((By.ID,'q')))
最长时间之内 满足wait.until中的那条件,则正常获取到元素,
超过最长时间还未获取到,则抛出异常
判断条件 -- 查文档
4) 前进后退
browser.back()
browser.forward()
browser.close()
5) cookies
coo = browser.get_cookies() # 获取cookies
browser.add_cookie({一系列键值对}) # 把字典里的cookie添加进去
browser.delete_all_cookies()
6) 选项卡管理
新打开一个选项卡
通过执行一个 js 的方式打开
browser.execute_script('window.open') # 通过JS打开一个新窗口选项卡
print(browser.window_handles) # 查看所有的选项卡 返回选项卡代号 列表形式
browser.switch_to_window(browser.window_handles[1]) #切换到选项卡
browser.get(url1)
time.sleep(1)
browser.switch_to_window(browser.window_handles[0]) # 切换到其他选项卡
browser.get(url2)
7) 异常处理
详细内容查看官方文档
try:
browser.get('http://www.baidu.com')
except TimeoutException:
print('Time Out')
try:
broeser.find_element_by_id('hello')
except NoSuchElementException:
print('No Element')
finally:
browser.close()