Python3简易爬虫常用操作
# 常用请求头
headers = {
"Host":"www.baidu.com",
"Referer":"https://www.baidu.com",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Connection": "keep-alive",
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0"
}
# requests常用代理配置样式,新版requests已支持socket5
# urllib的设置方式应该也是这样的,socket5的就用socket5://IP地址:端口
# 如果这里报错: 提示不支持socket5
# 安装 pip install PySocks
proxies = {
"http": "http://IP地址:端口号",
"https": "http://IP地址:端口号",
}
# 其他设置代理的方式
import socket
import socks
socks.set_default_proxy(socks.SOCKS5, "127.0.0.1", 1080)
socket.socket = socks.socksocket
# 如,在请求发起前设置可以作为socket5代理使用 :
import socks,socket,urllib.request
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5,"127.0.0.1",1080)
socket.socket =socks.socksocket
urllib.request.urlopen('https://www.ipip.net/').read()
常用参数
# 虽然我一般都用requests
# 但是有时候使用urllib获取的结果展示时面临着utf-8的乱码问题
# 可以使用下面的方法,在Python3中做展示时decode("UTF-8")即可专为unicode
'''
# 获取文件系统的编码类型
type = sys.getfilesystemencoding()
response.decode("UTF-8").encode(type)
'''
from urllib.request import urlopen
from urllib.request import urlretrieve
urlopen:
'''
创建一个表示远程url的类文件对象,然后像本地文件一样操作这个类文件对象来获取远程数据。
并非像requests和urlretrieve一样马上就进行下载,所以获取如果不是马上想下载资源的话用这个最好.
'''
urlretrieve:
'''直接将远程数据下载到本地.'''
请求参数类型
urlopen(url, data=None, proxies=None)
url = url 请求地址
data = data 请求参数
proxies = proxies 设置代理
urlretrieve(url,filename,reporthook,data)
url 请求地址
filename 本地保存名称
reporthook 回调函数,需要3个参数blocknum已经下载的数据块,blocksize数据块的大小,totalsize远程文件的大小
data 请求参数
响应参数
response = urlopen(url)
.read(),readline(),readlines(),fileno(),close() 这些方法的使用方式与文件对象完全一样
.info().get() 获取响应头信息.get()获取具体为哪个字段的响应头如Content-Length
.getcode() 获取响应状态码
.geturl() 返回请求的URL
import requests
请求参数
requests.get(url,headers,proxies,stream,cookies,params,allow_redirects,timeout)
url = url 请求地址
headers = headers 设置请求头
proxies = proxies 设置代理地址
stream = True 以流的形式进行下载(做分块下载时用)
cookies = cookies 设置请求cookie
params = params 通过GET形式进行传参即?key1=value1&key2=value2
allow_redirects = False 禁止跟随服务器进行重定向
timeout = timeout 设置请求超时时间
响应参数
response = requests.get()
response.cookies() 获取响应的cookie()参数为空是,为获取所有cookie
response.history 可以用来追踪重定向
response.encoding 获取/设置 响应内容的编码类型
response.text 获取响应的文本内容
response.content 获取二进制响应内容
response.json() 获取JSON格式的相应内容
response.iter_content(chunk_size) 获取响应的指定大小的块,请求参数需要设置stream=True
response.raw 获取相应的原始套接字, 请求参数需要设置stream=True.同时响应内容需要用.read(数字)来读取
r = requests.get('https://api.github.com/events', stream=True)
r.raw
r.raw.read(10)
响应状态码
requests.get().status_code 获取响应状态码
requests.codes.ok 内置的状态码查询对象可以和上面参数进行==判断是否成功
requests.get().raise_for_status 如果请求错误,由这里抛出异常如遇到403,500之类的
requests流下载控制
当使用requests的get下载大文件/数据时,建议使用使用stream模式。
通过使用Response.iter_content和Response.iter_lines方法
你可以进一步的控制工作流程,
或者通过Response.raw阅读底层urllib3的urllib3.HTTPResponse.
当把get函数的stream参数设置成False时,它会立即开始下载文件并放到内存中,
如果文件过大,有可能导致内存不足。
当把get函数的stream参数设置成True时,它不会立即开始下载,
当你使用iter_content或iter_lines遍历内容或访问内容属性时才开始下载。
需要注意一点:文件没有下载之前,它也需要保持连接。
'''
iter_content:一块一块的遍历要下载的内容,一般都是用这个
iter_lines:一行一行的遍历要下载的内容
chunk_size: 设置每块的大小,只有当stream为True是有效
'''
案例:
# 设置本次请求以流的形式进行下载
# 以块的形式处理接收到的数据, 并设置每块的大小
# 这里的header加不对很容易出现问题, 比如每次请求下载视频, 只是下一个空壳然后就进行下一个的下载
# 这里我基本上只用一个header就是Range,告诉服务器我下载到哪里了
response = requests.get(url, headers=header, stream=True)
with(open(filePath, 'ab')) as f:
for chunk in response.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
进度条
Tqdm 是一个快速,可扩展的Python进度条,
可以在 Python长循环中添加一个进度提示信息,
用户只需要封装任意的迭代器 tqdm(iterator)。
另外一个扩展trange和Tqdm用法一样, 不再累述
区别在于引入的过程和总量的数据类型
from tqdm import tqdm
from tqdm import trange
tqdm(接受一个list或者tuple,不接受字符串或整型)
trange(只能接受一个整型)
常用参数:
pbar = tqdm(
total=file_size,
initial=first_byte,
unit='B',
unit_scale=True,
desc=url.split('/')[-1]
disable=False
)
total
预期的迭代数目即预计下载的总量,默认为None,可以接受一个list和tuple
initial
初始计数器值,默认为0,如果做了断线重连,已下载部分记得要算进来
unit
将被用来定义每个单元的字符串,即下载量的计算单位如:B/K/M
unit_scale
如果设置,迭代的次数会自动按照十、百、千来添加前缀,默认为false
desc
进度条的描述
disable
是否显示进度条
后续调用参数,可以用来在后期来修改tqdm的的状态:
tqdm().set_description(str '进度条的描述内容')
用来设置在处理过程中设置进度条的描述, 不可再初始化配置时使用,而是在后期想要修改的时候调用
tqdm().update(int 更新数量)
用来手动更新进度条,
案例:
# 该方式会出现进度条效果,进度总量参数接受一个list
# 这种方式就是传入一个list然后tqdm按照list进行自动显示,用处比较少
from tqdm import tqdm
for i in tqdm(range(10000)):
time.sleep(0.01)
# 手动控制进度条的更新
from tqdm import tqdm
with tqdm(total=100) as pbar:
for i in range(10):
pbar.update(10)
pbar.close()
# 手动更新也可以这么操作
pbar = tqdm(total=100)
for i in range(10):
pbar.update(10)
pbar.close()
# 例如我在爬虫过程中使用tqdm输出进度条的流程如下
1. 首先获取到资源的总字节数,这里为什么不用reuquests().head是因为
在实际应用当中reuquests().head太占用网络带宽
urlopen().info().get('Content-Length')
2. 判断该文件是否已下载了一部分, 如果文件存在的话获取文件字节数
os.path.exists()
os.path.getsize()
3. 在http的请求头中设置Range, 这个参数我当时看http权威指南的时候到现在终于用到了
{"Range": "bytes=%s-%s" % (已下载文件的字节数, 文件总字节数)}
4. 初始化进度条,设置一下总量和计算单位k/b/m
tqdm()
5. 用刚才拼装的请求头去获取资源
requests.get()