自学Python第十四天- 一些有用的模块:urllib、requests 网络编程基础,向爬虫靠拢

  • fake_useragent 库
    • 安装 fake_useragent
    • 使用
  • urllib 库
    • urllib.request
      • request 的简单使用
        • urllib.request.urlopen 函数的参数
      • 获取 request 的状态码
      • 使用 urllib.request 设置请求头
      • 发送带数据的请求
      • https 请求
      • 使用代理服务器
      • 下载数据文件
    • urllib.error
    • urllib.parse
    • urllib.robotparser
  • requests 库
    • 简单发送请求
    • 关闭连接
    • 处理编码
    • 设置请求头
      • 查看请求头
    • 发送 post 请求
    • 发送附加参数的 get 请求
    • 通用请求
    • 使用cookie
    • 处理反爬
    • https 请求
    • 使用代理
    • 响应对象的常用属性和方法
    • 下载二进制文件

python 很大的一个优点就是爬虫编写方便,当然在写爬虫之前还需要网络编程的基础,毕竟爬虫是基于网络的程序。

fake_useragent 库

fake_useragent 是一个第三方库,作用仅仅是更换请求头中的 UserAgent ,伪装浏览器。因为用的比较方便,发送的请求都会用到,所以写在最前。

安装 fake_useragent

使用 pip install fake-useragent 进行安装,使用 from fake_useragent import UserAgent 引入使用。

使用

使用 UserAgent 对象的各种方法能生成 useragent 信息,例如:

from fake_useragent import UserAgentuseragent_chrome = UserAgent().chrome       # 模拟 chrome 浏览器生成 useragent 信息
useragent_random = UserAgent().random      # 随机模拟浏览器生成 useragent 信息

使用需要注意的是,尽量及时更新 fake_useragent 库

urllib 库

python 进行网络编程,可以使用 python 的内置库: urllib 库。urllib 库分为以下几个模块:

  • urllib.request :打开和读取 URL
  • urllib.error :包含 urllib.request 抛出的异常
  • urllib.parse :解析 URL
  • urllib.rebotparser :解析 robots.txt 文件

urllib.request

urllib.request 负责打开和读取 URL,是 urllib 库最重要也最常用的模块。其定义了一些打开 URL 的函数和类,包含授权验证、重定向、浏览器 cookkies 等。它可以模拟浏览器的一个请求发起过程。

request 的简单使用

request 最简单的用法就是模拟浏览器发送一个请求,并获取应答。

from urllib.request import urlopenurl = 'https://www.baidu.com'       # 设置请求地址
resp = urlopen(url)                    # 发送请求,并获得应答
print(resp.read().decode('utf-8') # 查看应答信息,因为默认是以二进制查看,所以需要解码为 utf-8

这样就获取到了应答信息。输出的是 html 文本,也可以写到文件中使用浏览器打开。

with open('mybaidu.html', 'w', encoding='utf-8') as file:file.write(resp.read().decode('utf-8'))

urllib.request.urlopen 函数的参数

urlopen 函数的全部参数如下:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

  • url :url地址,此参数也是唯一一个必须参数
  • data :发送到服务器的其他数据对象,默认 None
  • timeout :访问超时时间
  • cafile 和 capath :CA证书的文件名和路径,使用 HTTPS 需要用到
  • context :ssl.SSLContext 类型,用来指定 SSL 设置

获取 request 的状态码

发送请求后无论如何会收到一个状态码,这个状态码会表示该请求的响应状态。例如 200 成功、404 页面未找到等。

import urllib.requestmyURL1 = urllib.request.urlopen("https://www.runoob.com/")
print(myURL1.getcode())   # 200try:myURL2 = urllib.request.urlopen("https://www.runoob.com/no.html")
except urllib.error.HTTPError as e:if e.code == 404:print(404)   # 404

具体的状态码和含义可以看这里:

HTTP请求状态码

使用 urllib.request 设置请求头

我们抓取网页一般需要对 headers(网页头信息)进行模拟,这时候需要使用到 urllib.request.Request 类:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

  • url :url地址
  • data :发送请求的其他数据对象
  • headers :请求头信息,字典格式
  • origin_req_host :请求的主机地址,IP 或域名
  • unverifiable :很少用整个参数,用于设置网页是否需要验证
  • method :请求方法, 如 GET、POST、DELETE、PUT等
import urllib.requesturl = 'https://www.runoob.com/?s='  # 菜鸟教程搜索页面
keyword = 'Python 教程'
key_code = urllib.request.quote(keyword)  # 对请求进行编码
url_all = url + key_code
header = {'User-Agent': 'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}  # 头部信息
request = urllib.request.Request(url_all, headers=header)
response = urllib.request.urlopen(request)print(response.read().decode('utf-8'))

上面的例子是将请求头以实参形式传入,也可以使用 Request.add_header() 方法添加请求头信息。

import urllib.requesturl = 'http://www.baidu.com/'
req = urllib.request.Request(url)
req.add_header("User-Agent",'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36')
html = urllib.request.urlopen(req).read()

发送带数据的请求

因为 Request 类的数据信息必须是字节型的,所以需要使用 urllib.parse 进行编码

import urllib.request
import urllib.parseurl = 'https://www.runoob.com/try/py3/py3_urllib_test.php'  # 提交到表单页面
data = {'name':'RUNOOB', 'tag' : '菜鸟教程'}   # 提交数据
header = {'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}   #头部信息
data = urllib.parse.urlencode(data).encode('utf8')  # 对参数进行编码,解码使用 urllib.parse.urldecode
request=urllib.request.Request(url, data, header)   # 请求处理
response=urllib.request.urlopen(request).read()      # 读取结果
print(response.decode('utf-8'))

https 请求

import ssl# 忽略安全认证
context = ssl._create_unverified_context()
# 添加到 context 参数中
resp = urllib.request.urlopen(request,context = context)

使用代理服务器

使用代理服务器分为5步:设置代理、创建代理、应用代理、创建 Request 对象、发送访问请求:

import urllib.request# 设置代理
httpproxy_handler = urllib.request.ProxyHandler({'https': 'daili.com:8888'})
# 创建代理
opener = urllib.request.build_opener(httpproxy_handler)
# 将代理应用到全局
urllib.request.install_opener(opener)
# 创建 request 对象
request = urllib.request.Request(url)
# 发送请求
html = urllib.request.urlopen(request).read()

下载数据文件

可以使用 urllib.request.urlretrieve() 方法下载一些数据文件,例如图片等。

urllib.request.urlretrieve(url,filename)

urllib.error

urllib.error 模块为 urllib.request 所引发的异常定义了异常类,基础异常类是 URLError。urllib.error 包含了两个方法,URLError 和 HTTPError。

URLError 是 OSError 的一个子类,用于处理程序在遇到问题时会引发此异常(或其派生的异常),包含的属性 reason 为引发异常的原因。

HTTPError 是 URLError 的一个子类,用于处理特殊 HTTP 错误,例如作为认证请求的时候,包含的属性 code 为 HTTP 的状态码, reason 为引发异常的原因,headers 为导致 HTTPError 的特定 HTTP 请求的 HTTP 响应头。

例如对不存在的页面抓取并处理异常:

import urllib.request
import urllib.errormyURL1 = urllib.request.urlopen("https://www.runoob.com/")
print(myURL1.getcode())   # 200try:myURL2 = urllib.request.urlopen("https://www.runoob.com/no.html")
except urllib.error.HTTPError as e:if e.code == 404:print(404)   # 404
import urllib.request
import urllib.errordef download_with_retry(url,num_retries):print('下载中 ',url)try:# 下载网页并获取网页的 html 内容html = urllib.request.urlopen(url).read()except urllib.erroe.URLError as e:if hasattr(e, 'reason'):print('下载失败')print('失败原因:', e.reason)if hasattr(e, 'code'):print('服务器不能完成请求')print('错误代码:', e.code)if num_retries>0 and 500<=e.code<600:return download_with_retries(url,num_retries-1)return html

urllib.parse

urllib.parse 用于解析 URL,格式如下:
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)

  • urlstring 为字符串的 url 地址
  • scheme 为协议类型,
  • allow_fragments 参数为 false,则无法识别片段标识符。相反,它们被解析为路径,参数或查询组件的一部分,并 fragment 在返回值中设置为空字符串。
from urllib.parse import urlparseo = urlparse("https://www.runoob.com/?s=python+%E6%95%99%E7%A8%8B")
print(o)
# 输出结果
# ParseResult(scheme='https', netloc='www.runoob.com', path='/', params='', query='s=python+%E6%95%99%E7%A8%8B', fragment='')

也可以使用 urllib.parse.urlencode() 方法将数据(中文)进行编码,例如使用 urllib.request.Request 对象发送带数据的请求时的例子。

urllib.robotparser

urllib.robotparser 用于解析 robots.txt 文件。robots.txt(统一小写)是一种存放于网站根目录下的 robots 协议,它通常用于告诉搜索引擎对网站的抓取规则。

requests 库

requests 库也是 python 用于网络编程的一个库,由于是第三发库,所以需要进行安装。

requests 库的参考文档

简单发送请求

import requestsurl = 'https://www.sogou.com/web?query=周杰伦'
resp = requests.get(url)
print(resp)     # 执行结果: <Response [200]>
print(resp.text)    # 执行结果为页面内容

关闭连接

请求头中有一种设置:Connection: keep-alive ,如果不显式的断开连接,则会长时间占用TCP连接。通常可以发送一个请求报文,设置 Connection: close 。但是实际上其实可以直接对连接对象进行关闭。

resp.close() # 关闭 resp 连接

处理编码

一般在响应头或者是请求到的 html 文档中,会有文档编码 charset=utf-8 的注释,表示此文档使用哪种编码。此时如果直接查看是乱码的,可以设置编码后再进行查看

resp.encoding = 'utf-8'       # 使用 utf-8 编码
resp.encoding = resp.apparent_encoding     # 使用自适应编码,在不知道具体编码时候可以使用此项,正确率很高

设置请求头

上一个例子中,访问 https://www.sogou.com/web?query=周杰伦 时可以发现,浏览器可以正常访问,而 python 程序则不行。所以需要设置请求头,模拟普通浏览器发送请求来访问页面。

requests 库的请求头写在一个字典内,并且在发送请求时需要传递至方法实参。

import requestsurl = 'https://www.sogou.com/web?query=周杰伦'
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
}
resp = requests.get(url, headers=header)print(resp.text)

这里请求头里的 User-Agent 信息可以使用浏览器调试工具获取。

查看请求头

在爬虫测试中,如果被反爬了,则很大几率是出在请求头的 User-Agent 里。我们可以先查看下请求头信息。

import requestsurl = 'https://www.sogou.com/web?query=周杰伦'
resp = requests.get(url)
print(resp.request.headers)     # 输出请求头信息

发送 post 请求

发送 post 请求使用 requests.post() 方法。发送的数据是以字典形式传入实参。

import requestsurl = 'https://fanyi.baidu.com/sug'
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
}
d = {'kw': 'dog'}
resp = requests.post(url, headers=header, data=d)
print(resp.json())      # 以 json 字符串形式输出

发送附加参数的 get 请求

get 请求的参数除了可以直接写在 url 里,还可以使用附加方式发送:

import requestsurl = 'https://movie.douban.com/j/chart/top_list'
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
}
param = {'type': '24','interval_id': '100:90','action': '','start': 0,'limit': 20
}
resp = requests.get(url, headers=header, params=param)print(resp.request.url)
print(resp.json())

通用请求

可以使用 requests.request() 方法来发送任意类型的请求。

resp = requests.request(method, url, **kwargs)

其中 method 和 url 为必填项,**kwargs 是可选,可以加入参数、数据、json、请求头、cookies、文件、代理信息 等。

使用cookie

有些网站的页面请求需要 cookie 信息,一般 cookie 由浏览器存储在本地,使用 session 获取。使用 requests 进行请求时每次均是一个新的请求,所以先建立 session 进行登录,然后登录信息包括 cookie 就保存在了 session 中。

import requests# 建立会话
session = requests.session()
# 登录请求地址
url = 'https://passport.17k.com/ck/user/login'
# 请求登录会话(不需要返回值是因为登录的信息在cookie中,cookie信息保存在session里)
session.post(url, data={'loginName': 'xxxxxxxxx', 'password': 'xxxxxx'})
# 获取书架上的数据(使用session进行请求,则可以使用保存的cookie信息)
resp = session.get('https://user.17k.com/ck/author/shelf?page=1&appKey=xxxxxxxxx')
print(resp.json())

也可以使用在头部信息中添加 cookie 的方式直接进行请求

import requests# 也可以直接请求,在头部信息中添加 cookie 信息
resp = session.get('https://user.17k.com/ck/author/shelf?page=1&appKey=2406394919', headers={"Cookie": "GUID=xxxxxxxxxxxxxxxxxxxxxxxxxxx; sajssdk_2015_cross_new_user=1; c_channel=0; c_csc=web; accessToken=avatarUrl%3Dhttps%253A%252F%252Fcdn.static.17k.com%252Fuser%252Favatar%25xxxxxxxxxxxxxxxxxx33034.jpg-88x8xxxxxxxxxxxxxxxxxid%3D97233034%26nickname%3D%25Exxxxxxxxxxxx25E5%25A4%25A7%25E4%25BA%25A8%26e%3D1672538270%26s%3Dd0bfe4952e8fe4e2; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2297233034%2xxxxxxxxxxxxxxxxxxx181cbf9d99daa9-009b458c304258-57b1a33-2073600-181cbf9d99e67c%22%2C%22prxxxxxxxxxxxxxxxe%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9xxxxxxxxxxxxxxerrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%xxxxxxxxxxxxxxxxxx9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%xxxxxxxxxxxxxxx%22%7D%2C%22first_id%22%xxxxxxxxa388384-bf3dxxxxxxxxxxxxxxxxxx56%22%7D"
})
print(resp.json())

处理反爬

通常对于反爬,经常使用的手段就是验证 User-Agent ,验证 cookie ,防盗链 ,和 url 加密。对于验证可以在请求头部信息中增加响应信息,防盗链可以在请求头增加 Referer 信息,url 加密就需要进行分析了。

这里以下载梨视频的视频文件举例。通过分析页面和源代码可以发现视频 url 是经过了一个替换变形,那么获取到响应信息再替换回来就能得到正确的视频信息。

# 1. 拿到contId
# 2. 拿到videoStatus返回的json -> srcURL
# 3. srcURL里面的内容进行修整
# 4. 下载视频import requests# 视频页面地址
url = 'https://pearvideo.com/video_1759848'
contId = url.split('_')[1]
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36","Referer": url  # 防盗链:进行溯源,即请求的上一级页面
}
# 视频信息请求地址
videoStatusUrl = f'https://pearvideo.com/videoStatus.jsp?contId={contId}&mrd=0.5621134865680251'
# 获取相应json
resp = requests.get(videoStatusUrl, headers=headers)
# 从json中获取正确的视频地址
dic = resp.json()
srcUrl = dic['videoInfo']['videos']['srcUrl']
systemTime = dic['systemTime']
srcUrl = srcUrl.replace(systemTime, f'cont-{contId}')
# 下载视频
filename = './download/' + srcUrl.split('/')[-1]
with open(filename, mode='wb') as f:f.write(requests.get(srcUrl).content)

https 请求

resp = requests.get(url,verify=False)      # 忽略安全认证

使用代理

requests 使用代理和 urllib 使用代理类似,将代理字典(包含协议、地址+端口)以实参形式传入请求的形参 proxies 即可。

proxies = {"http": "39.130.150.44:80"   # 举个例子
}
resp = requests.get(url, headers=head, proxies=proxy)

响应对象的常用属性和方法

不管使用 get 还是 post 发送了请求后,会返回一个 Response 对象,可以通过此对象的一些属性和方法获得我们想要的数据:
r = requests.get('https://www.baidu.com')

  • r.status_code :返回状态码
  • r.reason :返回请求失败原因(请求成功返回 OK)
  • r.cookies :返回请求 cookies
  • r.headers :返回响应头
  • r.encoding :返回或设置响应内容的编码
  • r.content :返回响应内容(二进制内容)
  • r.text :返回响应内容的文本(相当于 r.content.decode(‘utf-8’))
  • r.json() :将响应内容 json 化并返回
  • r.request :返回发送的请求信息

下载二进制文件

可以使用 r.content 直接获取二进制文件内容

img_resp = requests.get(srcUrl)     # 请求图片
with open('img.jpg', mode='wb') as f:f.write(img_resp.content)     # 写入二进制数据

也可以使用二进制流的方式获取原始套接字响应。使用分片能够处理大文件,可以边获得二进制响应边写入文件。当使用流下载时,优先推荐此种方法。

img_resp = requests.get(srcUrl, stream=True)
with open('img.jpg', mode='wb') as f:for chunk in img_resp.iter_content(chunk_size):       # chunk_size 是分片读取的每一片的大小,单位字节f.write(chunk)

自学Python第十四天- 一些有用的模块:urllib、requests 网络编程基础,向爬虫靠拢相关推荐

  1. 孤荷凌寒自学python第十四天python代码的书写规范与条件语句及判断条件式

    孤荷凌寒自学python第十四天python代码的书写规范与条件语句及判断条件式 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 在我学习过的所有语言中,对VB系的语言比较喜欢,而对C系和J系 ...

  2. 无字天书之Python第十四页(time和calendar模块)

    博客目标 传送门 time模块 常用time模块中方法 calendar 到这里无字天书之Python基础算是快要结束了-(有可能还有下一篇基础篇操作) 感谢各路神仙的学习和陪伴... 未完待续-关注 ...

  3. python私有函数实现_024孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘...

    (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我们定义类时是否在类的内部代码块中定义过它们,这些私有方法都是存在的.比 ...

  4. 自学Python第二十六天- Tornado 框架

    自学Python第二十六天- Tornado 框架 安装及基础引用 创建.配置.初始化应用及简单运行服务 创建应用 对 app 进行设置 另一种设置方法 一些其他的配置 关于调试模式 设置路由处理器 ...

  5. 自学Python第十九天-flask框架

    自学Python第十九天-flask框架 安装和引用 使用 创建和运行应用 设置应用 处理函数及路由 另一种路由注册 唯一URL和重定向行为 反向解析 响应 get 和 post 请求 ,以及其他类型 ...

  6. 《OpenCv视觉之眼》Python图像处理十四 :Opencv图像轮廓提取之Scharr算法和Canny算法

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  7. Linux(b站视频兄弟连)自学笔记第十四章——日志管理

    Linux(b站视频兄弟连)自学笔记第十四章--日志管理 简介 rsyslogd 日志轮替 简介 rsyslogd 日志轮替

  8. 第十四届蓝桥杯集训——练习解题阶段(无序阶段)-基础练习 特殊回文数

    第十四届蓝桥杯集训--练习解题阶段(无序阶段)-基础练习 特殊回文数 目录 第十四届蓝桥杯集训--练习解题阶段(无序阶段)-基础练习 特殊回文数 前言 基础练习 特殊回文数 C语言 C++语言 Jav ...

  9. 第十四届蓝桥杯集训——练习解题阶段(无序阶段)-基础练习 字母图形

    第十四届蓝桥杯集训--练习解题阶段(无序阶段)-基础练习 字母图形 目录 第十四届蓝桥杯集训--练习解题阶段(无序阶段)-基础练习 字母图形 前言 基础练习 字母图形 C语言 C++语言 Java语言 ...

最新文章

  1. 2015/6/2站立会议(补发)
  2. 计算机数字信号原理,计算机网络通信原理数字信号的基带传输.ppt
  3. C语言位运算实现加法
  4. MTK DDR不能兼容分析
  5. 华为c语言编程规范_单片机开发之C语言编程基本规范
  6. Confluent官博:Kafka最牛队列,性能15倍于RabbitMQ!
  7. 犹太教、基督教和伊斯兰教的简单关系
  8. 电脑wifi热点软件_手机WiFi信号太差怎么办?掌握这些方法,轻松解决这个问题...
  9. 请教Parser Generator 开发工具中关于Lex和Yacc的问题
  10. ubuntu中颜色拾取器的安装以及16进制ARGB值在线转颜色
  11. MyBatis-Plus配置全局sql注入器后,BaseMapper中方法失效
  12. 软件测试——风险分析
  13. 生产环境实战spark (10)分布式集群 5台设备 SPARK集群 HistoryServer WEBUI不能打开问题解决 File file:/tmp/spark-events does not
  14. 【vim环境配置】详细实录
  15. NVIDIA Jetson之UART功能开发
  16. 伦巴时间步的动作要领_伦巴前进步动作的基本要领
  17. Mouse Controler(手机操控鼠标)
  18. Packet Data Convergence Protocol (PDCP)阅读笔记
  19. 嵌入式开发什么时候需要用RTOS?
  20. MySQL中三种表关系的建立

热门文章

  1. 爬取网易云音乐排行榜
  2. 二叉树的遍历 详解及实现
  3. OSD的主要实现方法和类型
  4. 输入法/非输入法切换 无法取消快捷键问题 以及 shift按键关闭CapsLock问题
  5. 《VSTO开发入门教程》配套资源下载
  6. Rabbitmq---生产者和消费者概念
  7. 操作系统课设——编程演示三种管理方式的地址换算过程
  8. 投资大师索罗斯的人生轨迹 索氏投资理论 打跨英格兰银行的人 “魔鬼”索罗斯...
  9. html引入微软雅黑,网页引入特殊字体的几种方案
  10. 网页CAD 网页浏览和编辑DWG