1.urllib中request构建完整请求
"""request构建完整请求""" from urllib import request # Request封装url req = request.Request("https://python.org") # 发起请求并保存请求结果 res = request.urlopen(req) # 打印响应信息 print(res.read().decode("utf-8")) """ class Request: def __init__(self, url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None): 参数解析: url:请求URL data:跟urlopen里面的data传递一样的bytes类型数据 headers:请求头可直接构造,也可以使用类方法add_header()传递参数 origin_req_host:请求时的host名称或者IP unverifiable:权限操作,有或者没有。默认False,表示用户没有权限选择接受这个请求的结果 method:请求时的方法,比如GET,POST,DELETE等 """ from urllib import request, parse # 设置请求的url url = "http://httpbin.org/post" # 设置请求头信息 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36", "Host": "httpbin.org" } dict = {"name": "Germey"} # 把字典转换成字节流信息 data = bytes(parse.urlencode(dict), encoding="utf8") # 参数按值传递 req = request.Request(url=url, data=data, headers=headers, method="POST") # 发起请求并保存请求结果 res = request.urlopen(req) # 打印响应信息 print(res.read().decode("utf-8"))
2.request中urlopen的get请求分析
"""urlopen的get分析""" from urllib import request from http.client import HTTPResponse # 引用 res = request.urlopen("https://www.python.org") print(type(res)) # 打印返回结果的类型,用from引用这个类型查看具备的方法和属性 print(res.status) # 返回相应的状态码 print(res.getheaders()) # 返回所有请求头信息 print(res.getheader("Server")) # 返回服务器信息,nginx。socket服务器中比较牛逼的一种 # def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, # *, cafile=None, capath=None, cadefault=False, context=None): """ 源码解释: 打开URL url,可以是字符串或Request对象。 * data *必须是指定要发送到的其他数据的对象 服务器,如果不需要这样的数据,则为None。请参阅请求 细节。 urllib.request模块使用HTTP / 1.1并包含“Connection:close” HTTP请求中的标头。 可选的* timeout *参数指定超时(以秒为单位) 阻塞操作,如连接尝试(如果未指定,则 将使用全局默认超时设置)。这仅适用于HTTP, HTTPS和FTP连接。 如果指定了* context *,则它必须是描述的ssl.SSLContext实例 各种SSL选项。有关更多详细信息,请参阅HTTPSConnection。 可选的* cafile *和* capath *参数指定一组可信CA. HTTPS请求的证书。 cafile应该指向一个文件 包含一捆CA证书,而capath应指向a 哈希证书文件的目录。更多信息可以在中找到 ssl.SSLContext.load_verify_locations()。 * cadefault *参数被忽略。 此函数始终返回可用作上下文的对象 经理和有方法,如 * geturl() - 返回检索到的资源的URL,常用于 确定是否遵循重定向 * info() - 返回页面的元信息,例如标题 email.message_from_string()实例的形式(请参阅快速参考 HTTP标头) * getcode() - 返回响应的HTTP状态代码。引发URLError 关于错误。 对于HTTP和HTTPS URL,此函数返回http.client.HTTPResponse 对象略有修改。除了以上三种新方法外,还有 msg属性包含与reason属性相同的信息--- 服务器返回的原因短语 - 而不是响应 在HTTPResponse的文档中指定的标头。 对于遗留显式处理的FTP,文件和数据URL以及请求 URLopener和FancyURLopener类,这个函数返回一个 urllib.response.addinfourl对象。 """
3.request中urlopen的post请求分析
"""urlopen的post请求分析""" from urllib import parse from urllib import request import json # 转换utf8编码的data数据 data = bytes(parse.urlencode({"word": "hello"}), encoding="utf8") # parse.urlencode({"word": "hello"}) 返回字符串形式'word=hello' print(data) # b'word=hello' 返回bytes类型数据与下面json区别 print(type(data)) # <class 'bytes'> res = request.urlopen("http://httpbin.org/post", data=data) print(res) # <http.client.HTTPResponse object at 0x00000184DB1C3E10> 返回响应对象 print(type(res)) # <class 'http.client.HTTPResponse'> 对象类型 print(res.read()) # 读取返回的内容中b'"form":{"word":"hello"},'此字段表明模拟了表单提交的方式 arg = json.dumps({"word": "hello"}) print(arg) # '{"word": "hello"}' json返回字符串形式字典数据 print(type(arg)) # <class 'str'>
4.request中urlopen的异常处理
"""urllib的异常处理""" from urllib import request, error try: res = request.urlopen("https://home.cnblogs.com/u/Guishuzhe/1") except error.HTTPError as e: # 先捕获子类详细异常原因 print(e.reason, e.code, e.headers) except error.URLError as e: # 再用父类捕获子类中没有的异常 print(e.reason) else: print("Request Successfully") import socket from urllib import request from urllib import error try: # 设置超时时间timeout=0.2 res = request.urlopen("http://httpbin.org/get", timeout=0.2) # 捕捉超时异常,返回友好信息 except error.URLError as e: print(type(e.reason)) # class URLError(OSError):源码 self.reason属性, e.reason调用这个属性 # 内置函数isinstance判断错误对象是不是某一类型 # 在这里是连接超时错误socket.timeout if isinstance(e.reason, socket.timeout): print("超时了")
5.urllib进阶设置Handler
"""urllib进阶设置Handler工具""" from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener from urllib.error import URLError username = "username" password = "password" url = "http://127.0.0.1:8000/" # 实例化一个待处理对象 p = HTTPPasswordMgrWithDefaultRealm() # 给实例化对象添加请求参数realm=None等.. p.add_password(None, url, username, password) # class AbstractBasicAuthHandler:找到父类并实例化出具体请求对象(Handler) auth_handler = HTTPBasicAuthHandler(p) # build_opener()方法接受*Handlers任意个Handler对象进行去重等处理,返回Opener对象 opener = build_opener(auth_handler) try: # 开始请求 res = opener.open(url) # 获取请求结果 html = res.read().decode("utf8") print(html) except URLError as e: # 打印错误信息 print(e.reason) """ HITPDefaultErrorHandler :用于处理HTTP响应错误,错误都会抛出HTTPError类型的异常 HTTPRedirectHandler :用于处理重定向 HTTPCookieProcessor 用于处理Cookies ProxyHandler :用于设置代理默认代理为空 HπPPasswordMgr :用于管理密码,它维护了用户名和密码的表 HTTPBasicAuthHandler 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题 """
6.cookies的处理
"""cookies的处理""" from http import cookiejar from urllib import request # 存放cookie信息 filename = "cookies.txt" cookie = cookiejar.LWPCookieJar(filename) # 建议使用此保存格式 # cookie = cookiejar.MozillaCookieJar(filename) handler = request.HTTPCookieProcessor(cookie) opener = request.build_opener(handler) res = opener.open("http://www.baidu.com") cookie.save(ignore_discard=True, ignore_expires=True) # 读取cookie信息 cookie = cookiejar.LWPCookieJar() # 实例化LWP对象 # 指定要读取的文件数据到cookie实例,忽略丢弃和忽略过期 cookie.load("cookies.txt", ignore_discard=True, ignore_expires=True) # 将读取的cookie信息封装为handler类型 handler = request.HTTPCookieProcessor(cookie) # 创建一个opener对象 opener = request.build_opener(handler) # 调用opener对象的open方法打开url res = opener.open("http://www.baidu.com") print(res.read().decode("utf-8"))
7.代理设置
"""urllib的代理设置""" from urllib.error import URLError from urllib.request import ProxyHandler, build_opener # 设置代理请求的类型、ip和端口,_parse_proxy函数完成代理参数解析 proxy_handler = ProxyHandler({ "http": "http://124.231.16.75:9000", "https": "https://113.105.201.193:3128" }) # 封装设置的代理数据,制造opener对象 opener = build_opener(proxy_handler) try: # 调用opener的open方法代理访问百度 res = opener.open("https://www.baidu.com") print(res.read().decode("utf-8")) except URLError as e: print(e.reason)
8.url的解析
"""urllib中的parse模块""" from urllib.parse import urlparse # 等同from urllib.parse import urlsplit from urllib.parse import urlunparse # 等同from urllib.parse import urlunsplit # urljoin拼接主url和所需url参数形成完整的url from urllib.parse import urljoin # base_url + new_url = complete_url from urllib.parse import urlencode # 构造GET请求参数,序列化完整url # 反序列化url参数 from urllib.parse import parse_qs # from urllib.parse import parse_qsl from urllib.parse import quote # 解决中文编码问题,默认utf-8编码 from urllib.parse import unquote # 进行URL解码 # 解析url的标准格式 res = urlparse("http://www.baidu.com/index.html;user?id=5#comment") print(type(res), res) """ # 返回ParseResult结果的对象 <class 'urllib.parse.ParseResult'> ParseResult(scheme='http', # 协议 netloc='www.baidu.com', # 域名 path='/index.html', # 路径 params='user', # 参数 query='id=5', # 查询条件,一般get查询时使用 fragment='comment' # 锚点,定位页面内部的下拉位置 ) scheme://netloc/path;params?query#fragment 标准格式的url """ # urlunparse拼接url,需要6个参数完成拼接,限制比较大 data = ["https", "www.baidu.com", "index.html", "user", "id=5", "comment"] print(urlunparse(data)) # urljoin拼接,常用此拼接方法,可自动补全完整的url连接 print(urljoin("https://www.baidu.com", "s?ie=utf-8&tn=baidu&wd=girl")) # urlencode构造GET请求参数,常用方法。用字段存储url所需参数,使用时再进行转换 params = { "name": "Jim", "age": "26" } base_url = "https://www.baidu.com?" url = base_url + urlencode(params) print(url) # parse_qs反序列化url参数{'name': ['Jim'], 'age': ['26']}, parse_qsl转换为元组组成的列表 query = "name=Jim&age=26" print(parse_qs(query)) # quote方法可以将内容转换为URL编码的格式,默认utf-8编码 keyword = "机械键盘" url = "https://www.baidu.com/s?wd=" + quote(keyword) print(url) # unquote方法可以将已编码的URL解码 url = "https://www.baidu.com/s?wd=%E6%9C%BA%E6%A2%B0%E9%94%AE%E7%9B%98" print(unquote(url))
9.蜘蛛协议
""" 百度!!! 分析Robots协议,Robots协议也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准(Robots Exclusion Protocol),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取它通常是一个叫作 robots.txt 的文本文件,一般放在网站的根目录下 User-agent: * *通配符,表示对所有爬虫都有效,此处可以设置爬虫名称 Disallow: / /不允许抓取所有页面,不允许抓取的目录 Allow: /public/ 可以抓取的目录,和Disallow一起使用 urllib的robotparser模块 set_url():用来设置robots.txt文件的链接如果在创建RobotFileParser对象时传入了链 接,那么就不需要再使用这个方法设置了 read ():读取robots.txt文件并进行分析.注意,这个方法执行一个读取和分析操作,如果不 调用这个方法接下来的判断都会为False,所以一定记得调用这个方法这个方法不会返 回任何内容,但是执行了读取操作 parse():用来解析robots.txt文件,传人的参数是robots.txt某些行的内容,它会按照robots.txt 的语法规则来分析这些内容 can_fetch():该方法传人两个参数第一个是User-agent,第二个是要抓取的URL返回的 内容是该搜索引擎是否可以抓取这个URL,返回结果是True或False mtime():返回的是上次抓取和分析robots.txt的时间,这对于长时间分析和抓取的搜索爬虫 很有必要的,你可能需要定期检查来抓取最新的robots.txt modified():它同样对长时间分析和抓取的搜索爬虫很有帮助,将当前时间设置为上次抓取 和分析robots.txt的时间 """ from urllib.robotparser import RobotFileParser from urllib.request import urlopen from urllib import request # 创建RobotFileParser对象 rp = RobotFileParser() # 设置连接 rp.set_url("https://www.jianshu.com/robots.txt") # 读取分析 rp.read() # 打印判断的结果,直接无模拟访问抓取都返回False print(rp.can_fetch("*", "https://www.jianshu.com/p/b67554025d7d")) # False print(rp.can_fetch("*", "https://www.jianshu.com/search?q=python&page=1&type=collections")) # False # 需要添加headers信息,不添加直接403.模拟浏览器访问抓取 url = "https://www.jianshu.com/robots.txt" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36" } req = request.Request(url=url, headers=headers) res = urlopen(req).read().decode("utf-8").split(" ") rp = RobotFileParser() rp.parse(res) print(rp.can_fetch("*", "https://www.jianshu.com/p/b67554025d7d")) # True print(rp.can_fetch("*", "https://www.jianshu.com/search?q=python&page=1&type=collections")) # False