从网页抓取数据(计算机学院大数据专业大三的错误出现,有纰漏之处)
优采云 发布时间: 2021-09-11 00:10从网页抓取数据(计算机学院大数据专业大三的错误出现,有纰漏之处)
大家好,我不温柔,我是计算机学院大数据专业的大三学生。我的外号来自一个成语——不温柔,希望我有温柔的气质。博主作为互联网行业的新手,写博客一方面记录自己的学习过程,另一方面总结自己犯过的错误,希望能帮助到很多刚入门的年轻人他是。不过由于水平有限,博客难免会出现一些错误。如有疏漏,希望大家多多指教!暂时只会在csdn平台更新,
PS:随着越来越多的人未经本人同意直接爬到博主文章,博主特此声明:未经本人许可禁止转载! ! !
内容
前言
网络爬虫的一般流程
一、了解网址
基本 URL 收录以下内容:
模式(或协议)、服务器名(或IP地址)、路径和文件名,如“protocol://authorization/path?query”。带有授权部分的完整统一资源标识符语法如下所示:协议://用户名:密码@子域名。域名。顶级域名:端口号/目录/文件名。文件后缀?参数=值#符号。
例如:
二、常用的获取网页数据的方式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协议
context: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、Opener
开场导演:
5、cookie
示例:获取百度 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 库
Requests 是基于 urllib 用 python 语言编写的,使用 Apache2 Licensed 开源协议的 HTTP 库。与 urllib 相比,Requests 更方便,可以为我们节省很多工作。建议爬虫使用 Requests 库。
官方文档链接:
1、Requests 库安装
在终端运行以下命令:pip install requests
2、使用请求发起请求
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。不仅如此,我们可能得到的响应非常强大,可以直接获取很多信息,而且响应中的内容不是一次性的,响应的内容会自动读出并保存在文本变量中您可以根据需要多次阅读。其次,我们来看看响应中的有用信息:
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 是什么样子的一目了然
除了上面的信息,response还提供了很多其他的信息。另外,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 参数对于每个键也可以有多个值。这可以通过创建数据元组列表或以列表作为值的字典来完成。当表单有多个使用相同键的元素时,这尤其有用:
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。此外,请求的文档是完整的。这里我们主要讲解请求最强大最常用的功能:会话保留。上面的代码中,如果我们连续发起两次请求都没有关系,会导致部分数据不可用。如:
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默认会忽略所有请求的cookies,即使是重定向的请求,请求会在一个请求中保存cookies(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!是不是很简单。其实requests的内部cookies也用到了cookielib,有兴趣的同学可以深入探讨一下。
请求库的功能:
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上的很多练习都没有用,因为requests很简单易学!当然没有白费,urllib2是一个非常基础的网络库。许多其他网络库,包括请求,都是基于 urllib2 开发的。前面的练习有助于我们更好地理解网络,理解Python对网络的处理,这对我们以后开发可靠高效的爬虫大有裨益。
注意:
内容
响应以 unicode 编码。为了方便阅读,我们需要将其转换为中文。直接打印是不行的,因为python在将dict转换为字符串时保留了unicide编码,所以直接打印的不是中文。
这里我们使用另一种转换方法:先将得到的form dict转换成unicode字符串(注意ensure_ascii=False参数,表示unicode字符没有转义),然后将得到的unicode字符字符串编码成一个UTF-8字符串,最后转成dict方便输出。
三、Browser 简介
Chrome 提供了检查网页元素的功能,称为 Chrome Inspect。您可以在网页上右键查看该功能,如下图所示:
在这个页面调用Chrome Inspect,我们可以看到类似如下的界面:
通常我们最常用的功能是查看一个元素的源代码,点击左上角的元素定位器,可以选择网页中不同的元素,HTML源代码区会自动显示源代码指定元素的,通常CSS显示区域也会显示应用于该元素的样式。 Chrome Inspect 比较常用的功能是监控网络交互过程。在功能栏中选择Network,看到如下界面:
Chrome Network的交互区展示了一个网页加载过程以及浏览器发起的所有请求。选择一个请求,右侧会显示请求的详细信息,包括请求头、响应头、响应内容等。Chrome网络是我们研究网页交互过程的重要工具。 Cookie 和 Session 是重要的网络技术。您还可以在 Chrome Inspect 中查看网络 cookie。在功能栏中选择应用,看到如下界面:
在 Chrome 应用程序的左侧选择 Cookies,您可以看到以 K-V 形式保存的 cookie。这个功能在我们研究网页的登录过程时非常有用。需要注意的是,在研究一个完整的网络交互过程之前,记得右键点击Cookies,然后点击Clear清除所有旧的Cookies。
HTTP 响应的第一行,状态行收录状态代码。状态码由三位数字组成,表示服务器对客户端请求的处理结果。状态码分为以下几类:
1xx:信息响应类型,表示收到请求并继续处理
2xx:处理成功响应类,表示动作成功接收、理解和响应
3xx:重定向响应类,为了完成指定的动作,必须进行进一步的处理
4xx:客户端错误,客户端请求收录语法错误或服务器无法理解
5xx:服务器错误,服务器无法正确执行有效请求
以下是一些常见的状态代码及其说明:
200 OK:请求已被正确处理和响应。
301 Move Permanently:永久重定向。
302 Move Temporously:临时重定向。
400 Bad Request:服务器无法理解请求。
需要 401 身份验证:需要验证用户身份。
403 Forbidden:禁止访问资源。
404 Not Found:找不到资源。
405 Method Not Allowed:对资源使用了错误的方法。例如,应该使用POST,而使用PUT。
408 请求超时:请求超时。
500 内部服务器错误:内部服务器错误。
501 方法未实现:请求方法无效。如果可能,将 GET 写为 Get。
502 Bad Gateway:网关或代理收到来自上游服务器的错误响应。
503 Service Unavailable:服务暂时不可用,您可以稍后尝试。
504 Gateway Timeout:网关或代理请求上游服务器超时。
在实际应用中,大部分网站都有反爬虫策略。响应状态码代表服务器的处理结果,是我们调整爬虫爬取状态(如频率、ip)的重要参考。比如我们一直正常运行的爬虫,突然收到403响应。这可能是因为服务器识别了我们的爬虫并拒绝了我们的请求。这时候就得减慢爬取频率,或者重启Session,甚至改IP。
美好的日子总是短暂的。虽然我还想继续和你谈谈,但这篇博文现在已经结束了。如果还不够,别着急,我们下篇文章见!
我从不厌倦阅读一本好书数百遍。而如果我想成为全场最漂亮的男孩子,我必须坚持通过学习获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
如果我的博客对你有帮助,如果你喜欢我的博客内容,听说喜欢的人不会太幸运,每天都精力充沛!如果你真的想当妓女,祝你天天开心,欢迎访问我的博客。
码字不易,大家的支持是我坚持下去的动力。