300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 自学Python第十四天- 一些有用的模块:urllib requests 网络编程基础 向爬虫靠拢

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

时间:2024-02-07 00:42:49

相关推荐

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

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

fake_useragent 库安装 fake_useragent使用urllib 库urllib.requestrequest 的简单使用urllib.request.urlopen 函数的参数获取 request 的状态码使用 urllib.request 设置请求头发送带数据的请求https 请求使用代理服务器下载数据文件urllib.errorurllib.parseurllib.robotparserrequests 库简单发送请求关闭连接处理编码设置请求头查看请求头发送 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 :打开和读取 URLurllib.error :包含 urllib.request 抛出的异常urllib.parse :解析 URLurllib.rebotparser :解析 robots.txt 文件

urllib.request

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

request 的简单使用

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

from urllib.request import urlopenurl = ''# 设置请求地址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 :发送到服务器的其他数据对象,默认 Nonetimeout :访问超时时间cafile 和 capath :CA证书的文件名和路径,使用 HTTPS 需要用到context :ssl.SSLContext 类型,用来指定 SSL 设置

获取 request 的状态码

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

import urllib.requestmyURL1 = urllib.request.urlopen("/")print(myURL1.getcode()) # 200try:myURL2 = urllib.request.urlopen("/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 = '/?s=' # 菜鸟教程搜索页面keyword = 'Python 教程'key_code = urllib.request.quote(keyword) # 对请求进行编码url_all = url + key_codeheader = {'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 = '/'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.requestimport urllib.parseurl = '/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.urldecoderequest=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': ':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.requestimport urllib.errormyURL1 = urllib.request.urlopen("/")print(myURL1.getcode()) # 200try:myURL2 = urllib.request.urlopen("/no.html")except urllib.error.HTTPError as e:if e.code == 404:print(404) # 404

import urllib.requestimport 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("/?s=python+%E6%95%99%E7%A8%8B")print(o)# 输出结果# ParseResult(scheme='https', netloc='', 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 = '/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# 使用自适应编码,在不知道具体编码时候可以使用此项,正确率很高

设置请求头

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

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

import requestsurl = '/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 = '/web?query=周杰伦'resp = requests.get(url)print(resp.request.headers)# 输出请求头信息

发送 post 请求

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

import requestsurl = '/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 = '/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 = '/ck/user/login'# 请求登录会话(不需要返回值是因为登录的信息在cookie中,cookie信息保存在session里)session.post(url, data={'loginName': 'xxxxxxxxx', 'password': 'xxxxxx'})# 获取书架上的数据(使用session进行请求,则可以使用保存的cookie信息)resp = session.get('/ck/author/shelf?page=1&appKey=xxxxxxxxx')print(resp.json())

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

import requests# 也可以直接请求,在头部信息中添加 cookie 信息resp = session.get('/ck/author/shelf?page=1&appKey=2406394919', headers={"Cookie": "GUID=xxxxxxxxxxxxxxxxxxxxxxxxxxx; sajssdk__cross_new_user=1; c_channel=0; c_csc=web; accessToken=avatarUrl%3Dhttps%253A%252F%252Fcdn.%252Fuser%252Favatar%25xxxxxxxxxxxxxxxxxx33034.jpg-88x8xxxxxxxxxxxxxxxxxid%3D97233034%26nickname%3D%25Exxxxxxxxxxxx25E5%25A4%25A7%25E4%25BA%25A8%26e%3D1672538270%26s%3Dd0bfe4952e8fe4e2; sensorsdatajssdkcross=%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 = '/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'/videoStatus.jsp?contId={contId}&mrd=0.5621134865680251'# 获取相应jsonresp = 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('')

r.status_code :返回状态码r.reason :返回请求失败原因(请求成功返回 OK)r.cookies :返回请求 cookiesr.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)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。