Python爬虫新手村上手指南③

259 阅读3分钟

urllib简介与urllib.parse的使用

urllib 是Python自带的标准库中用于网络请求的库,无需安装,直接引用即可。

通常用于爬虫开发,API(应用程序编程接口)数据获取和测试

urllib库的4大模块

urllib.request 用于打开和读取url

urllib.error 包含提出的例外(异常)urllib.request

urllib.parse 用于解析url

urllib.robotparser 用于解析robots.txt文件

import urllib.request

url = 'https://www.runoob.com/'

#发送请求
resp = urllib.request.urlopen(url)
#decode将byte类型转成str类型
html = resp.read().decode('utf-8')
print(html)

urllib.request发送get与post请求

urllib.request库

模拟浏览器发起一个HTTP请求,并获取请求响应结果

urllib.request.urlopen的语法格式

urlopen

参数说明

url:url参数是str类型的地址,也就是要访问的URL

data:默认值为None,urllib判断参数data是否为none从而区分请求方式。

参数data为None,则代表请求方式为get,反之请求方式为post,发送post请求。

参数data以字典形式存储数据,并将参数data由字典类型转换成字节类型才能完成post请求

urlopen函数返回的结果是一个 http.client.HTTPResponse对象

import urllib.request
import urllib.parse
url = 'https://juejin.cn/passport/web/user/login/?account_sdk_source=web'

data = {
    'username': 'admin',
    'password': '@Test123$%^',
    'captcha': '1',
    'key': '1650535293946'
}
#发送请求
resp = urllib.request.urlopen(url, data=bytes(urllib.parse.urlencode(data), encoding='utf-8'))
html = resp.read().decode('utf-8')
print(html)

构造Request对象发送请求

Request

如果在请求中需要加入headers(请求头)

指定请求方式等信息,那么就可以利用更加大的Request来构建一个请求

语法

urllib.request.Request(url, data=None,headers={},method=None)

案例:爬取豆瓣网

movie.douban.com/

如果直接用 urlopen

urllib.request.Request(url, data=None,headers={},method=None)

import urllib.request

url = 'https://movie.douban.com/'
resp = urllib.request.urlopen(url)
print(resp)

报错 418 发送请求遇到服务器端反爬虫,服务器拒绝响应数据

urllib.error.HTTPError: HTTP Error 418:

为了应对这种简单的反爬方式,添加一个请求头,伪装成浏览

修改代码如下:

1.构建请求对象

2.使用urlopen打开请求

3.从响应结果中读取数据

import urllib.request

url = 'https://movie.douban.com/'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'}

#构建请求对象
req = urllib.request.Request(url, headers=headers)
#使用urlopen打开请求
resp = urllib.request.urlopen(req)
#从响应结果中读取数据
html = resp.read().decode('utf-8')
print(html)

urlopen()方法的源代码

查看源码,发现是通过一个 build_opener() 方法创建了一个_opener

global _opener
if cafile or capath or cadefault:
    import warnings
    warnings.warn("cafile, capath and cadefault are deprecated, use a "
                  "custom context instead.", DeprecationWarning, 2)
    if context is not None:
        raise ValueError(
            "You can't pass both context and any of cafile, capath, and "
            "cadefault"
        )
    if not _have_ssl:
        raise ValueError('SSL support not available')
    context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH,
                                         cafile=cafile,
                                         capath=capath)
    https_handler = HTTPSHandler(context=context)
    opener = build_opener(https_handler)
elif context:
    https_handler = HTTPSHandler(context=context)
    opener = build_opener(https_handler)
elif _opener is None:
    _opener = opener = build_opener()
else:
    opener = _opener
return opener.open(url, data, timeout)

构建自己的opener发送请求

import urllib.request
url = 'https://www.baidu.com/'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'}
#构建请求对象
req = urllib.request.Request(url, headers=headers)
#获取opener对象
opener = urllib.request.build_opener()

resp = opener.open(req)
print(resp.read().decode())

IP代理

为什么需要使用IP代理

假如一个网站它会检测某一段时间某个IP的访问次数,

如果访问次数过多,它会禁止你的访问。

所以,你可以设置一些代理服务器来帮助你做工作,

每隔一段时间换一个代理。

IP代理的分类

透明代理:

目标网站,知道你使用了代理,并且知道你的源IP地址,

这种代理显然不符合我们这里使用代理的初衷

匿名代理:

匿名程序比较低,也就是网站知道你使用了代理,但是并不知道你的源IP地址

高匿代理:

这是最保险的方式,目录网站既不知道你使用了代理,更不值得你的源IP

如何使用IP代理

from urllib.request import build_opener
from urllib.request import ProxyHandler

proxy = ProxyHandler({'http':'106.54.128.253:999'})
opener = build_opener(proxy);

# url = 'https://www.baidu.com/'
url = 'https://smallpdf.com/cn/'
resp = opener.open(url)
print(resp.read().decode('utf-8'))

IP代理,就是为了防止反爬,所使用的。

解析与异常处理

异常处理主要用到两大类

urllib.error.URLError

用于捕获urllib.request产生的异常,使用reason属性返回错误原因

urllib.error.HTTPError

用于处理HTTP与HTTPS请求的错误,

它有三个属性

code 请求返回的状态码

reason 返回错误的原因

headers 请求返回的响应头信息