爬虫的概念
爬虫就是:模拟浏览器发送网络请求,获取请求响应
爬虫的分类
聚焦爬虫:针对特定网站的爬虫
通用爬虫:搜索引擎的爬虫
爬虫的流程
url ---> 发送请求,获取响应 ----> 提取数据 ---> 保存
获取响应 ---> 提取url地址,继续请求
浏览器的请求过程
浏览器获取的数据包含:url地址对应的响应+js+css+jpg
爬虫会获取:url地址对应的响应
爬虫获取的内容和elements内容不一样,进行数据提取的时候,需要根据url地址对应的响应为准
http的重点(请求头)
user-agent:告诉对方服务器是什么客户端正在请求资源,能够达到模拟浏览器的效果
cookie:获取登录只有才能够访问的资源
python2和python3中的字符串
ascii 一个字节表示一个字符
unicode 两个字节表示一个字符
utf-8 变长的编码方式,1、2、3字节表示一个字符
python2
字节类型:str,字节类型,通过decode()转化为unicode类型
str.decode()
unicode类型:unicode ,通过encode转化为str字节类型
unicode.encode("utf-8")
python3
str:unicode,通过encode() 转化为bytes
str.encode()
bytes:字节类型,通过decode()转化为str类型
bytes.decode()
requests如何发送请求和获取响应
response = requests.get(url)
response.text -> str
response.encoding="utf-8"
response.content -> bytes
response.content.decode()
发送带headers的请求
headers = {"User-Agent": "从浏览器中复制"}
requests.get(url, headers=headers)
发送带参数的请求
params = {"": ""}
url_temp = "不完整的URL地址"
requests.get(url_temp, params=params)
发送post请求
data = {"从浏览器中form data的位置寻找"}
requests.post(url, data=data)
requests中使用代理
proxies = {协议:协议 + ip + 端口}
requests.get(url, proxies=proxies)
使用代理的目的:
反反爬
隐藏真实ip
代理的分类
高匿名:不知道在使用代理
匿名:知道在使用代理,但是不知道真实ip
透明:对方知道真实的ip
session的使用
session = requests.Session()
session.post(url, data) # cookie会存在session中
session.get(url) # 会带上之前的cookie
列表推导式
In [41]: [i for i in range(10)]
Out[41]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [42]: [i/2 for i in range(10)]
Out[42]: [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]
In [43]: [i/2 for i in range(10) if i%2==0]
面向对象
对象:生活中的客观事物
类:对事物的抽象,在代码中实现class类型
实例:使用之前对类的实例化之后的记录
三元运算符的使用
if 条件成立,if前面的结果赋值给to,否则else后面的内容赋值给to
to = "en" if lan == "zh" else "zh"
requests模拟登录的两类方法
1.session实例化对象
session = requests.Session()
session.get(url) # cookie保存在session中
session.get(url) # 带上保存在session中cookie
2.requests进行携带cookie登录
cookie字符串放在headers中
headers = {"cookie_name": "cookie_value"}
resp = requests.get(url, headers=headers)
把cookie字典交给requests请求方法的cookies
cookies = {"cookie_name": "cookie_value"}
resp = requests.get(url, cookies=cookies)
字典推导式
In [8]: {i:i+10 for i in range(10)}
Out[8]: {0: 10, 1: 11, 2: 12, 3: 13, 4: 14, 5: 15, 6: 16, 7: 17, 8: 18, 9: 19}
In [9]: {i:i+10 for i in range(10) if i%2==0}
Out[9]: {0: 10, 2: 12, 4: 14, 6: 16, 8: 18}
寻找登录接口的方法
1.form表单action对应的url地址
用户名和密码的input标签中,name的值作为键,用户名和密码作为值的字典,作为post data
2.通过抓包,定位url地址
form data
分析js,获取加密的数据
1.观察变化
2.确定js的位置
从event listener中寻找
search all file中寻找关键字
3.进行分析
通过添加断点的方式分析js
4.执行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,进行异常捕获,重新执行被装饰的函数
@retry(stop_max_attempt_number=3)
def _func():
pass
def func():
try:
_func()
except Exception as e:
print(e)
爬虫中数据的分类
结构化数据:json,xml
直接使用模块转化为python类型
非结构化数据:html
re,xpath
json是什么
数据交换格式
json模块的使用
json.loads(json_str) # json字符串转化为python类型
json.dumps(python_type, ensure_ascii=False, indent=2) # python类型转化为json字符串
json.load() # 把包含json的类文件对象中的数据提取出来转化为python类型
json.dump() # python类型转化为json格式存入类文件对象中
正则的语法
字符
`.` 匹配到出了\n之外的所有字符,re.S模式下可以匹配\n
`\` 转义
`[]` 或的效果,从中选择一个, `[abc]+` 能够匹配多个
`|` 或的效果,选择`|`两边的内容
预定义的字符集
`\d` 数字
`\s` 空白字符串,包含空格、\n,\t
`\w` 单词字符,`a-zA-Z0-9_`
数量词
`*` 匹配0次或者多次
`+` 匹配一次或者多次
`?` 能够匹配0-1次,让*,+非贪婪
re模块的常用方法
re.findall("正则表达式", "待匹配的字符串") # 返回列表,或者是空列表
re.sub("regex", "_", "待替换的字符串") # 返回字符串
re.compile("regex", re.S/re.DOTALL) # 返回一个p模型
p.findall("待匹配的字符串")
p.sub("_", "待替换的字符串")
原始字符串r
定义:特殊符号原本的字面意思
用途:
正则中,能够忽略转义符号带来的影响
windows文件路径
xpath语法
`//` 的用途
`//a` 当前html页面上的所有的a
`bookstore//book` bookstore下的所有的book元素
`div//a` div中所有的a,包括div下的后代节点中的a
`a//text()` a下的所有的文本
`@` 的使用
`//a/@href` 获取所有的a标签下的href的值
`//title[@lang="eng"]` 选择lang=eng的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(bytes或者str类型的字符串) # 返回element
element.xpath("xpath字符串") # 返回列表
etree.tostring(element) # 返回bytes类型字符串
# 数据提取时:先分组,再提取数据
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(target=func, args=(,))
t1.setDaemon(True) # 设置为守护线程
t1.start() # 此时线程才会启动
from queue import Queue
q = Queue()
q.put() # 计数+1
q.get() # 计数不会-1
q.join() # 让主线程阻塞,等待队列任务计数,计数为0结束
q.task_done() # 和get一起,计数-1
多进程中进程和队列的使用
p = multiprocessing.Process(targe=func)
p.damone = True # 设置为守护进程,主进程结束,子进程结束
p.start()
from multiprocessing import JoinableQueue
q = JoinableQueue()
q.put() # 计数+1
q.get() # 计数不会-1
q.join() # 让主进程阻塞,等待队列任务计数,计数为0队列任务结束
q.task_done() # 和get一起,计数-1
线程池和协程池的使用
from multiprocessing.dummy import Pool # 线程池
pool = Pool(5)
pool.apply_async(func, callback=func2)
import gevent.monkey
gevent.monkey.patch_all()
from gevent.pool import Pool
pool = Pool(5)
pool.apply_async(func, callback=func2)