什么是爬虫
模拟浏览器发送请求,获取响应
爬虫的分类,请求的流程
- 聚焦爬虫:针对特定网站的爬虫
- 通用爬虫:搜索引擎的爬虫
url—->发送请求,获取响应—->提取数据—->保存
发送请求,获取数据—->提取url地址,继续请求
浏览器发送请求的过程
- 爬虫请求的:url地址对应的响应
- 浏览器获取的内容:elements的内容=url对应的响应+js+css+图片
- 需要根据url地址对应的响应为准进行数据的提取
user-agent有什么用
- 告诉服务器是谁正在发送请求
- 爬虫中通过把user-agent设置为浏览器的ua,能够达到模拟浏览器的效果
requests如何发送请求和响应
- response = requests.get(url)
- response.text -> str
- response.encoding=“utf-8”
- response.content -> bytes
- response.conten.decode()
python3和python2字符串的转化
-
python2
- unicode
- unicode.encode()
- str:字节类型
- str.decode()
-
python3
- str
- str.encode()
- bytes
- bytes.decode()
requests和headers如何使用
- headers = {‘USER-Agent’:’’}
- requests.get(url,headers=headers)
requests如何发送post请求
- data = {“浏览器中的form data”}
- requests.post(url,data=data)
requests中如何使用代理,使用代理的目的,代理分类
- proxies = {协议:协议+ip+端口}
- requests.get(url,proxies=proxies)
目的:- 反反爬
- 隐藏真实ip
代理的分类:
– 高匿名:不知道在使用代理
– 匿名:知道在使用代理,不知道真实ip
– 透明:对方知道真实的ip
requests中session类如何使用,为什么使用session
- session = requests.Session()
- session.post(url,data) cookie保存在session
- session.get(url) 带上之前的cookie
列表推导式如何使用
- [i for i in range(10) if i%2==0]
三元运算符
if 条件成立,if前面的结果赋值给to,否则else后面的结果赋值给to
to= ‘en’ if lan==‘zh’ else ‘zh’
requests进行携带cookie登录
- cookie字符串放在headers中
- 把cookie字典交给requests请求方法的cookies
寻找登录接口的方法
-
form表单action对应的url地址
- 用户名和密码对应的input标签中,name的值为键,用户名和密码作为值的字典,作为post,data
-
通过抓包,定位url地址
- form data
分析js,获取加密的数据
-
观察变化
-
定位js
- 通过event listener定位js的位置
- 通过搜索url地址的关键字,通过chrom的search all file来进行搜索
-
进行分析
- 通过添加断点的方法分析js
-
执行js
- 完全的使用python模拟js的执行过程
requests处理ssl证书
requests.get(url,verify=False)
获取响应中的cookie,转化为字典
response = requests.get(url,headers=headers)
requests.utils.dict_from_cookiejar(response.cookies)
超时参数的使用
requests.get(url,timeout=3)
retrying模块的使用
- from retrying import retry
- 通过装饰器的方式使用retry进行异常捕获,重新执行被装饰的函数
数据分类
-
结构化数据
- json,xml
- 直接使用模块转化为python类型
-
非结构化数据
- html
- re,xpath
json模块的使用
json.loads:json字符串转化为python类型
json.dumps:python类型转化为json字符串
json.load:包含json字符串的类文件对象转化为python类型
json.dump:把python类型存入类文件对象中
requests模拟登陆的三种方法
-
session
- 实例对象
- session.get(url) # cookie保存在session中
- session.get(url) # 带上保存在session中的cookie
-
cookie放在headers中
-
cookie传递给cookies参数
- cookie={“cookie的name值”:“cookie的value对应的值”}
js分析的流程
- 确定js的位置
- 从event listener中寻找
- search all file中寻找关键字
- 添加断点的方法,观察执行过程
- 执行js
requests中超时参数的使用,retrying模块的使用
- requests.get(url,timeout=3)
from retrying import retry @retry(stop_max_attempt_number=3) def fun(): pass
-
xpath语法
-
// 的用途
- //a 当前html页面上的所有的a
- bookstore/book bookstore下的所有的book元素
-
@的使用
- //a/@href 所有的a的href
- //title[@class='end'] 选择class=end的title标签
-
text()的使用
- //a/text() 获取所有的a下的文本
- //a[text()='下一页'] 获取文本为下一页的a标签
- a//text() a下的所有的文本
-
xpath查找特定的节点
- //a[1] 选择第一个
- //a[last()] 最后一个
- //a[position()<4] 前三个
-
-
lxml模块的使用
from lxml import etree
element = etree.HTML(html_str) # bytes或者str类型的字符串
element.xpath("xpath str") # 返回列表
etree.tostring(element) # 转化为字符串
# 数据提取时:先分组,在提取
1. 正则表达式的复习
特殊字符
- .
能够匹配除了n之外的所有的字符
- []
能够匹配方括号中列出的任意一个字符
In [1]: import re
In [2]: re.findall("[qwe]","qweertert") Out[2]: ['q', 'w', 'e', 'e', 'e']
如果想匹配方括号中的多个字符,使用[]+。例如[qwe]+ ,表示匹配qwe中的多个字符
In [1]: import re
In [2]: re.findall("[qwe]+","qweertert") Out[2]: ['qwee', 'e']
如果想表示取反,使用^ 。例如[^qwe] ,表示匹配除了qwe之外的所有字符
In [1]: import re
In [2]: re.findall("[^qwe]","qweertert") Out[2]: ['r', 't', 'r', 't']
In [3]: re.findall("[^qwe]+","qweertert") Out[3]: ['rt', 'rt']
-
*
能够匹配 0 或 无穷多个字符(贪婪匹配)
-
+
能够匹配 1 或 无穷多个字符(贪婪匹配)
-
?
能够匹配 1 或 0 个字符(非贪婪匹配)
-
{}
表示前一个字符出现的次数
d | 数字 0-9 |
D | 非数字 [^d] |
w | 字母、数字、下划线 [a-zA-Z0-9_] |
W | 除了字母、数字、下划线的所有字符 |
s | 空白字符 [tnrfv] |
S | 非空白字符 |
正则中的方法
re.findall('reg',str)
返回 所有的匹配结果
re.sub('reg',’替换后的字符串‘,str)
替换 字符串中的相关字符
re.compile('reg',re.S)
编译,对正则表达式进行编译
re.match('reg',str)
返回 从开头匹配的结果
re.search('reg',str)
返回 字符串中匹配到的第一个结果
2. xpath语法的复习
-
/
表示根节点
-
//
表示任意节点
-
.
表示当前节点
-
@
选取节点的属性
-
text()
获取标签的文本
//a/text()
//a[text()='下一页']
3. lxml模块的使用
首先需要安装lxml包
pip install lxml
from lxml import etree import requests
# 发送请求,获取响应 response = requests.get('http://www.baidu.com') response = response.content.decode()
# etree.HTML() 接收字符串 seleclt_res = etree.HTML(response)
# 返回的列表 url_list = seleclt_res.xpath("//a/@href")
print(url_list)
xpath的包含
- ‘//a[contains(text(),“下一页”)]’ 选择文本包含下一页三个字的a标签
- ‘//a[contains(@class,‘n’)]’ class包含n的a标签
url地址解码
requests.utils.unquote(url)
准备url地址
- 不知道url地址的规律,知道一共多少页,准备url列表, 果壳,糗百
- 不知道url地址规律,或者不知道一共多少页,准备start_url, 贴吧
多线程爬虫
为了能够让主线程回收子线程,可以把子线程设置为守护线程,即该线程不重要,主线程结束,子线程结束
- threading
- t1 = threading.Thread(targe=func,args=(,))
- t1.setDaemon(True)
- t1.start() #此时线程才会启动
- 队列
- q.join()# 阻塞主线程,让主线程等待队列任务结束之后再结束,队列任务在计数为0时结束
- q.task_done() 和 get()方法配合,队列计数-1
- q.put() 队列计数+1
多进程爬虫
- from multiprocessing import Process
- t1 = Process(targe=func,args=(,))
- t1.daemon = True #设置为守护进程
- t1.start() #此时线程才会启动
多进程中队列的使用
- 多进程中使用普通的队列模块会发生阻塞,对应的需要使用multiprocessing提供的JoinableQueue模块,其使用过程和在线程中使用的queue方法相同
线程池爬虫
-
from multiprocessing.dummy import Pool
-
pool = Pool(5)
-
pool.apply_async(func, callback=fun2)
-
import gevent.monkey
-
gevent.monkey.patch_all()
-
from gevent.pool iport Pool
-
pool = Pool(5)
-
pool.apply_async(func,callback=func2)
定位元素的方法
- driver.find_element # 返回第一个元素,如果没有报错
- driver.find_elements # 返回包含元素的列表,如果没有返回空列表
获取属性和文本的方法
- 获取文本:element.text
- 获取属性值:element.get_attribute(“href”)
切换frame
- driver.switch_to.frame(id,name,element)
验证码的识别
-
url地址不变,验证码不变
- 请求验证码的地址,获取响应,进行识别
-
url地址不变,验证码变化
- 请求验证码,发送登录请求,需带上一套cookie,才能够登录成功,对应可以使用requests.Session()来实现
-
selenium处理验证码
- 带上selenium的driver中的cookie来请求验证码
- selenium截屏,获取验证
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试