Python-爬虫之requests
一、urllib返回的响应对象
# 1个对象类型
# ------------------------------------
print(type(response)) # <class 'http.client.HTTPResponse'>
# 6个方法
# ------------------------------------
# 1. read()
# 功能:一个字节一个字节的读
# 返回:二进制字节类型
content = response.read() # 读取全部
content = response.read(6) # 读 n 个字节
# 2. readlines()
# 功能:一行一行的读,直到读取完
# 返回:返回列表,每个元素是每行数据的二进制字节类型
content = response.readlines().
# 3. readline()
# 功能:读取第一行,只读取一行
# 返回:二进制字节类型
content = response.readline()
# 4. getcode()
# 功能:返回状态码 【如果是 200 则说明正确,如果是 404、、 等,就是错误】
# 返回:整数类型
print(response.getcode())
# 5. geturl()
# 功能:获取 url 地址
# 返回:字符串
print(type(response.geturl()))
二、爬虫常见坑点处理
'''
url参数编码的问题:
-- 使用 url 请求数据时,可以携带参数
-- 但是参数中不可以有中文,如果有中文需要转化为 Unicode编码
'''
'''
UA(User-Agent)问题:
-- 中文名为用户代理,是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA
-- 是一种向访问网站提供你所使用的浏览器类型及版本、操作系统及版本、浏览器内核、等信息的标识
-- UA可以进行伪装
-- 如果需要频繁访问某个站点,建议多换几个UA使用
'''
'''
Cookie反扒
-- 访问个人主页,但是这是主页是需要登录之后才可以访问
-- 所以如果用爬虫访问该页面,访问的是登录界面,而不是主页
-- 此时就需要 cookie登录
-- 因为 cookie 中包含了访问页面时需要的数据,所有才可以访问成功
-- 我们可以先登录,找到登录后的 cookie,之后在进行爬取数据
'''
'''
报错:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte
原因:
服务端响应的数据是压缩后的版本
解决方法:
-- 方法1:
去掉请求头的一个参数对 "accept-encoding: gzip, deflate, br"
-- 方法2:
# (1) 将 数据转换成 流数据
buff = BytesIO(response.read())
# (2) 对流数据进行解压
f = gzip.GzipFile(fileobj=buff)
# (3) 读取流数据,并转换格式
content = f.read().decode('utf-8')
'''
'''
报错:
urlopen error [Errno 11001] getaddrinfo failed
原因:
不知,听说设计源码的问题
解决方法:
将 url 的单引号,改成双引号即可
'''
'''
报错:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb0 in position 255: invalid start byte
原因:
中文字符的Unicode编码0x0800-0xFFFF之间,(utf-8包含了部分汉字)
当你试图将该“中文字符”转成U码的utf-8时超出了其范筹
而GBK 规范收录了 ISO 10646.1 中的全部 CJK 汉字和符号,并有所补充
解决方法:
将 `response.read().decode('utf-8')` 改为 `response.read().decode('gbk')`
'''
'''
报错:
'gb2312' codec can't encode character '\xa0' in position 2: illegal multibyte sequence
解决方法:
方法1.
-- 在转换前将 '\xa0' 替换掉
-- string.replace(u’\xa0’, u’ ‘);
方法2.
-- 在gbk解码时忽略掉不能解码的数据
-- fp.write(content.encode("gbk", 'ignore').decode("gbk", "ignore"))
原因:
gbk无法转换’\xa0’字符
说明是将Unicode字符编码为GBK时候出现问题,可能是本身Unicode类型的字符中,包含了一些无法转换为GBK编码的一些字符,此时出错的数据不多,忽略它即可
'''
三、通用的get请求
import urllib.parse
import urllib.request
try:
# 1. 提供基础url
baseUrl = 'https://www.bilibili.com'
# 2. 提供url的参数
data = {
# 没有的话,就不写
}
# 3. 将参数转变为Unicode编码,且用'&'连接成字符串
data = urllib.parse.urlencode(data)
# 4. 拼接为完整的 url
url = baseUrl + data
# 5. 提供请求头
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
}
# 6. 定制请求对象
request = urllib.request.Request(url=url, headers=headers)
# 7. 发送请求
response = urllib.request.urlopen(request)
# 8. 读取相应数据
content = response.read()
# 9. 解码数据
content = content.decode('utf-8')
# 10. 处理数据
print(content)
with open('bi.html', 'w', encoding='utf-8') as fp:
fp.write(content)
except urllib.error.HTTPError:
print('HTTPError:错误!!!')
except urllib.error.URLError:
print('URLError:错误!!!')
四、通用的post请求
import json
import urllib.parse
import urllib.request
try:
# 1. 提供基础url
baseUrl = 'https://fanyi.baidu.com/sug'
# 2. 提供url的参数
data = {
'kw': 'key',
}
# 3. 将参数转变为Unicode编码,并且用'&'连接成字符串
data = urllib.parse.urlencode(data)
# 4. 将参数进行编码【post比get多出的一步】
data = data.encode('utf-8')
# 5. 提供请求头
headers = {
'Referer': 'https://fanyi.baidu.com/translate?aldtype=16047&query=&keyfrom=baidu&smartresult=dict&lang=auto2zh',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
}
# 6. 定制请求对象
request = urllib.request.Request(url=baseUrl, data=data, headers=headers)
# 7. 发送请求
response = urllib.request.urlopen(request)
# 8. 读取相应数据
content = response.read()
# 9. 解码数据
content = content.decode('utf-8')
# 10. 处理数据
# 编码:保存到文件
with open('fanyi.json', 'w', encoding='utf-8') as fp:
# json.dump(content, fp) # 如果用这个方法,可能会报错
fp.write(content)
# 解码:从文件读出
with open('fanyi.json', 'r', encoding='utf-8') as fp:
data = json.load(fp)
print(data)
except urllib.error.HTTPError:
print('HTTPError:错误!!!')
except urllib.error.URLError:
print('URLError:错误!!!')
五、通用的get请求使用代理池
import urllib.parse
import urllib.request
from random import choice
try:
# 1. 提供基础url
baseUrl = 'https://www.bilibili.com'
# 2. 提供url的参数
data = {
# 没有的话,就不写
}
# 3. 将参数转变为Unicode编码,且用'&'连接成字符串
data = urllib.parse.urlencode(data)
# 4. 拼接为完整的 url
url = baseUrl + data
# 5. 提供请求头
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
}
# 6. 定制请求对象
request = urllib.request.Request(url=url, headers=headers)
# 7. 提供一个 代理池
proxise_pool = [
{'http': '47.242.66.236:4818'},
{'http': '47.242.190.60:11573'},
]
# 8. 随机获取一个代理
proxise = choice(proxise_pool)
# 9. 获取 handler 对象
handler = urllib.request.ProxyHandler(proxies=proxise)
# 10. 获取 opener 对象
opener = urllib.request.build_opener(handler)
# 11. 调用 open 方法,模拟浏览器向服务器发送请求,并获得响应对象
response = opener.open(request)
# 12. 读取相应数据
content = response.read()
# 13. 解码数据
content = content.decode('utf-8')
# 14. 处理数据
print(content)
except urllib.error.HTTPError:
print('HTTPError:错误!!!')
except urllib.error.URLError:
print('URLError:错误!!!')
六、通用的post请求使用代理池
import json
import urllib.parse
import urllib.request
from random import choice
try:
# 1. 提供基础url
baseUrl = 'https://fanyi.baidu.com/sug'
# 2. 提供url的参数
data = {
'kw': 'key',
}
# 3. 将参数转变为Unicode编码,并且用'&'连接成字符串
data = urllib.parse.urlencode(data)
# 4. 将参数进行编码【post比get多出的一步】
data = data.encode('utf-8')
# 5. 提供请求头
headers = {
'Referer': 'https://fanyi.baidu.com/translate?aldtype=16047&query=&keyfrom=baidu&smartresult=dict&lang=auto2zh',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
}
# 6. 定制请求对象
request = urllib.request.Request(url=baseUrl, data=data, headers=headers)
# 7. 提供一个 代理池
proxise_pool = [
{'http': '47.242.66.236:4818'},
{'http': '47.242.190.60:11573'},
]
# 8. 随机获取一个代理
proxise = choice(proxise_pool)
# 9. 获取 handler 对象
handler = urllib.request.ProxyHandler(proxies=proxise)
# 10. 获取 opener 对象
opener = urllib.request.build_opener(handler)
# 11. 调用 open 方法,模拟浏览器向服务器发送请求,并获得响应对象
response = opener.open(request)
# 12. 读取相应数据
content = response.read()
# 13. 解码数据
content = content.decode('utf-8')
# 14. 处理数据
# 编码:保存到文件
with open('fanyi.json', 'w', encoding='utf-8') as fp:
# json.dump(content, fp) # 如果用这个方法,可能会报错
fp.write(content)
# 解码:从文件读出
with open('fanyi.json', 'r', encoding='utf-8') as fp:
data = json.load(fp)
print(data)
except urllib.error.HTTPError:
print('HTTPError:错误!!!')
except urllib.error.URLError:
print('URLError:错误!!!')