网页抓取解密(常用的获取网页数据的方式2.1URLlib:未经本人允许,禁止转载! )
优采云 发布时间: 2022-02-12 21:09网页抓取解密(常用的获取网页数据的方式2.1URLlib:未经本人允许,禁止转载!
)
大家好,我不温不火,我是计算机学院大数据专业的三年级学生。我的绰号来自成语——不冷不热,意思是希望我有一个温柔的气质。博主作为互联网行业的新手,写博客一方面是为了记录自己的学习过程,另一方面是总结自己的错误,希望能帮助很多和自己一样处于起步阶段的新人。不过由于水平有限,博客难免会出现一些错误。如果有任何错误,请给我您的建议!暂时只在csdn平台更新,博客主页:.
PS:由于越来越多的人未经本人同意直接爬博主文章,博主特此声明:未经本人允许,禁止转载!!!
内容
前言
网络爬虫的一般流程
一、理解 URL
基本 URL 收录以下内容:
模式(或协议)、服务器名称(或IP地址)、路径和文件名,如“protocol://authorization/path?query”。带有授权部分的完整 URI 语法如下所示:protocol://username:password@subdomain。域名。顶级域名:端口号/目录/文件名.filesuffix?parameter=value#sign。
例如:
二、获取网页数据的常用方法2.1 URLlib
这里我们先看一个小demo
# 百度首页
import urllib.request
response = urllib.request.urlopen("http://www.baidu.com")
html = response.read().decode("utf-8")
print(html)
2.2、urllib.request
官方文档(有兴趣可以自己查看):
1、urllib.request.urlopen
urllib.request.urlopen(url,data = None,[timeout,]*,cafile = None, capath = None, cadefault = False,context = None)
timeout:释放链接的超时时间
cafile/capath/cadefault:CA认证参数,用于HTTPS协议
上下文:SSL 链接选项,用于 HTTPS
2、urllib.request.Request
urllib.request.Request(url,data = None,headers = {},origin_req_host = None,unverifiable = False,method = None)
代码详情:
# coding=utf-8
from urllib import request
from urllib.parse import urlparse
url = "http://httpbin.org/post"
headers = {
"user-agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0'
}
dict = {"name":"buwenbuhuo"}
data = bytes(urllib.parse.urlencode(dict),encoding = "utf8")
req = request.Request(url=url,data=data,headers=headers,method="POST")
response = request.urlopen(req)
print(response.read().decode("utf-8"))
3、urllib.request 的高级特性
urllib.request 几乎可以在任何 HTTP 请求中执行所有操作:
4、开瓶器
开场导演:
5、cookies
示例:获取百度 Cookie
import http.cookiejar,urllib.request
cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open("http://www.baidu.com")
for item in cookie:
print(item.name+"="+item.value)
filename = 'cookie.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)
2.3、请求库
Requests 是基于 urllib 的 python 编写的,使用 Apache2 Licensed 开源协议的 HTTP 库。Requests 相比 urllib 更方便,可以为我们省去很多工作。建议爬虫使用 Requests 库。
官方文档链接:
1、请求库安装
在终端中运行以下命令: pip install requests
2、使用requests发起请求
import requests
import json
# 用requests发起简单的GET请求
url_get = 'http://httpbin.org/get'
response = requests.get(url_get,timeout = 5)
print(json.loads(response.text)['args'])
# 用requests发起带参数的GET请求
kvs = {'k1':'v1','k2':'v2'}
response = requests.get(url_get,params=kvs,timeout = 5)
print(json.loads(response.text)['args'])
# 用requests 发起POST 请求
url_post = 'http://httpbin.org/post'
kvs = {'k1':'v1','k2':'v2'}
response = requests.post(url_post,data=kvs,timeout = 5)
print(response.json()['form'])
从上图中我们可以看出,方法名很清楚的表达了发起的请求,get就是GET,post就是POST。不仅如此,我们的response非常强大,可以直接获取很多信息,而且response中的内容不是一次性的,requests会自动读取response的内容并保存在text变量中,读取你想要多少次。接下来,让我们看看响应中有哪些有用的信息:
print(response.url)
print(response.status_code)
print(response.headers)
print(response.cookies)
print(response.encoding) # requests会自动猜测响应内容的编码
import json
print(response.json() == json.loads(response.text)) # response.text 是响应内容,可以读取任意次,并且requests可以自动转换json
requests = response.request # 可以直接获取response对应的request
print(response.url)
print(response.headers) # 我们发起的request 是什么样子的一目了然
除了上述信息之外,响应中还提供了很多其他信息。另外,请求除了get和post之外,还提供了显式的put、delete、head、options方法,对应着相应的HTTP方法。有兴趣的读者可以进一步探索。
3、Requests 库发起 POST 请求
这部分摘自官方文档:
通常,如果您希望发送一些表单编码的数据 - 非常类似于 HTML 表单。为此,只需将字典传递给 data 参数。发出请求后,您的数据字典将自动进行表单编码:
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("https://httpbin.org/post", data=payload)
>>> print(r.text)
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
data参数也可以对每个key有多个值。这可以通过创建数据元组列表或列表值字典来完成。当表单有多个使用相同键的元素时,这尤其有用:
import requests
>>> payload_tuples = [('key1', 'value1'), ('key1', 'value2')]
>>> r1 = requests.post('https://httpbin.org/post', data=payload_tuples)
>>> payload_dict = {'key1': ['value1', 'value2']}
>>> r2 = requests.post('https://httpbin.org/post', data=payload_dict)
>>> print(r1.text)
{
...
"form": {
"key1": [
"value1",
"value2"
]
},
...
}
>>> r1.text == r2.text
True
4、requests.Session
import requests
# 创建一个session对象
s = requests.Session()
# 用session对象发出get请求,设置cookies
s.get('https://httpbin.org/cookies/set/sessioncookie/123456789')
# 用session对象发出另外一个get请求,获取cookies
r = s.get('https://httpbin.org/cookies')
# 显示结果
print(r.text)
请求的大部分用法与 urllib2 类似。此外,请求的文档非常完整。这里主要讲解request最强大、最常用的功能:会话持久化。在上面的代码中,我们连续发起的两个请求是不相关的,这会导致一些数据不可用。喜欢:
import requests
url_cookies = 'http://httpbin.org/cookies'
url_set_cookies = 'http://httpbin.org/cookies/set?k1=v1&k2=v2'
print(requests.get(url_cookies,timeout = 5).json())
print(requests.get(url_set_cookies,timeout = 5).json())
print(requests.get(url_cookies,timeout = 5).json())
可以看到,调用url_set_cookies设置cookie前后发起的GET请求获取的cookie都是空的。这意味着不同请求之间没有关系。有些人可能会对上面代码中第 5 行的输出感到惊讶,因为在上一篇 文章 我们用 urllib2 发出同样的请求时,结果仍然是空的。这确实有点奇怪,因为 urllib2 默认忽略所有请求的 cookie,即使是重定向请求,并且请求会在请求中保存 cookie(url_set_cookies 请求收录重定向请求)。
以下代码可以在一个会话中保留多个请求:
session = requests.Session()
print(requests.get(url_cookies,timeout = 5).json())
print(requests.get(url_set_cookies,timeout = 5).json())
print(requests.get(url_cookies,timeout = 5).json())
我们现在可以看到我们的第三个请求收录了第二个请求设置的 cookie!是不是很简单。其实cookielib也是用来把cookie保存在request里面的,有兴趣的同学可以深入探索一下。
请求库的特点:
6、设置代理
import requests
url = 'http://httpbin.org/cookies/set?k1=v1&k2=v2'
proxies = {'http':'http://username:password@host:port','http://username:password@host:port'}
print(requests.get(url,proxies = proxies,timeout = 5).json()['args'])
# 上面的方法要给每个请求都要加上proxies参数,比较繁琐,可以为每个session设置一个默认的proxies
session = requests.Session()
session.proxies = proxies # 一个session中的所有请求都使用同一套代理
print(session.get(url,timeout = 5).json()['args'])
上面的代码当然不会工作,因为代理格式不正确。当我们需要它时,我们可以直接重用这段代码。你可能会认为之前所有使用 urllib2 的练习都是徒劳的,因为请求非常容易学习!当然没有白费,urllib2是一个很基础的网络库,其他很多网络库,包括request都是基于urllib2开发的。前面的练习将帮助我们更好地理解网络,了解Python是如何处理网络的,这对我们以后开发可靠高效的爬虫大有裨益。
必须注意的是:
响应中的内容以 unicode 编码。为了方便阅读,我们需要将其转换成中文。直接打印是不行的,因为Python在将dict转成字符串时保留了unicide编码,所以直接打印不是中文。
这里我们使用另一种转换方式:先将得到的表单dict转换成unicode字符串(注意ensure_ascii=False参数,表示unicode字符不转义),再将得到的unicode字符串编码成UTF-8字符串,最后转换为 dict 以便于输出。
三、浏览器简介
Chrome 提供了一种检查网页元素的功能,称为 Chrome Inspect。该功能可以在网页上右击查看,如下图所示:
在这个页面调出 Chrome Inspect,我们可以看到类似下面的界面:
通常我们最常用的功能是查看一个元素的源代码。单击左上角的元素定位器可以选择网页中的不同元素。HTML源代码区会自动显示指定元素的源代码,通常CSS显示区也会显示这个应用于元素的样式。Chrome Inspect 比较常用的功能是监控网络交互过程。在功能栏中选择Network,可以看到如下界面:
Chrome 网络的交互区域展示了一个网页加载过程,浏览器发出的所有请求。选择一个请求,右侧会显示该请求的详细信息,包括请求头、响应头、响应内容等。Chrome Network是我们研究网页交互流程的重要工具。Cookie 和会话是重要的网络技术。您还可以在 Chrome Inspect 中查看网络 cookie。在功能栏中选择应用程序,看到如下界面:
在Chrome应用左侧选择Cookies,可以看到以KV形式保存的cookies。当我们研究网页的登录过程时,这个功能非常有用。需要注意的是,在研究一个完整的网络交互过程之前,记得右键点击Cookies,点击清除,清除所有旧的Cookies。
HTTP 响应的第一行,即状态行,收录状态代码。状态码由三位数字组成,表示服务器对客户端请求的处理结果。状态码分为以下几类:
1xx :信息响应类,表示收到请求,继续处理
2xx:处理成功响应类,表示动作成功接收、理解、响应
3xx : 重定向响应类,必须做进一步处理才能完成指定动作
4xx:客户端错误,客户端请求收录语法错误或服务器无法理解
5xx:服务器错误,服务器无法正确执行有效请求
以下是一些常见的状态码及其说明:
200 OK:请求已被处理并正确响应。
301 Move Permanently:永久重定向。
302 临时移动:临时重定向。
400 Bad Request:服务器不理解请求。
401 Authentication Required :需要用户验证。
403 Forbidden:禁止访问资源。
404 Not Found:找不到资源。
405 Method Not Allowed:资源使用了错误的方法,例如应该使用POST,但使用了PUT。
408 Request Timeout :请求超时。
500 内部服务器错误:内部服务器错误。
501 Method Not Implemented:请求方法无效,如果可能,将GET写成Get。
502 Bad Gateway : 网关或代理收到上游服务器的错误响应。
503 Service Unavailable :服务暂时不可用,您可以稍后尝试。
504 Gateway Timeout:网关或代理对上游服务器的请求超时。
在实际应用中,大部分网站都有反爬策略,响应状态码代表服务器的处理结果,是我们调整爬取状态(如频率、ip)的重要参考履带式。比如我们一直正常运行的爬虫突然得到403响应,很可能是服务器识别到了我们的爬虫,拒绝了我们的请求。这时候我们就需要放慢爬取频率,或者重启会话,甚至更换IP。
美好的日子总是短暂的。虽然我想继续和你聊天,但是这篇博文已经结束了。如果还不够好玩,别着急,我们下期再见!
一本好书读一百遍也不厌烦,熟了课才知道自己。而如果我想成为观众中最漂亮的男孩,我必须坚持通过学习获得更多的知识,用知识改变命运,用博客见证我的成长,用行动证明我在努力。
如果我的博客对你有帮助,如果你喜欢我的博客内容,请一键“点赞”“评论”“采集”!听说喜欢的人不会倒霉的,每天都精神抖擞!如果你真的想白嫖,那么祝你天天快乐,也欢迎经常光顾我的博客。
码字不易,大家的支持是我坚持下去的动力。喜欢后别忘了关注我哦!