网络爬虫:Requests库&&Robots协议

爬虫:Requests库&&Robots协议

Copyright: Jingmin Wei, Pattern Recognition and Intelligent System, School of Artificial and Intelligence, Huazhong University of Science and Technology

网络爬虫专栏链接



本教程主要参考中国大学慕课的 Python 网络爬虫与信息提取,为个人学习笔记。

在学习过程中遇到了一些问题,都手动记录并且修改更正,保证所有的代码为有效。且结合其他的博客总结了一些常见问题的解决方式。

本教程不商用,仅为学习参考使用。如需转载,请联系本人。

Reference

爬虫 MOOC

数据分析 MOOC

廖雪峰老师的 Python 教程

教程使用方式

有一定的 Python 基础,然后经常上网即可。

本教程主要是在 Pycharm 上运行的,当时年少不懂事, Python 还是装在 C 盘里,也没有用 Anaconda。

推荐大家一台电脑最多装一个 Python 解释器,编辑器用 VSCode + Jupyter Notebook 插件,环境为 Anaconda3 环境,且环境装在 DEF 盘(老生常谈了)。

具体的相关编程知识入门须知可以看我的另一篇文章 Pytorch:入门指南和GPU计算。

一、安装requests和lxml。

pip 是个 python 的基本包管理命令,详细的使用方式和请自行翻阅资料。

为啥用 pip,因为我们在安装 python3 的时候,选择了同时安装 pip 等一系列的包,不像 python2,还要一个一个去安装。

pip3 install requests
pip3 install lxml # 另一个爬虫库,可选

在这里插入图片描述

我已经安装,不需要重复安装

二、(引入)轻松爬取百度网页。

#-*- coding:utf-8 -*-
import requests #导入requests

url = 'https://www.baidu.com/'
data = requests.get(url) #下载百度首页内容 
data.encoding='utf-8' #更改编码方式 
data.text #打印结果

输出结果:

<!DOCTYPE html>

<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');

                </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>

三、requests库与HTTP协议

  • requests.request()

构造一个请求,支撑以下各方法的基础方法

  • requests.get()

获取 HTML 网页的主要方法,对应于 HTTP 的 GET

  • requests.head()

获取 HTML 网页头信息的方法,对应于 HTTP 的 HEAD

  • requests.post()

向 HTML 网页提交 POST 请求的方法,对应于 HTTP 的 POST

  • requests.put()

向 HTML 网页提交 PUT 请求的方法,对应于 HTTP 的 PUT

  • requests.patch()

向 HTML 网页提交局部修改请求,对应于 HTTP 的 PATCH

  • requests.delete()

向 HTML 页面提交删除请求,对应于 HTTP 的 DELETE

1.requests.request()

在这里插入图片描述

requests.get(url, params=None, **kwargs)

url 拟获取页面的url链接

params url中的额外参数,字典或字节流格式,可选

**kwargs: 12个控制访问的参数

r.status_code

HTTP 请求的返回状态,200 表示连接成功,404 表示失败

r.text

HTTP 响应内容的字符串形式,即 url 对应的页面内容

r.encoding

从 HTTP header 中猜测的响应内容编码方式

r.apparent_encoding

从内容中分析出的响应内容编码方式(备选编码方式)

r.content

HTTP 响应内容的二进制形式

# -*- coding:utf-8 -*-

import requests
url="http://www.baidu.com"
r=requests.get(url) #调用requests方法

if r.status_code==200:  #调用response方法
    print(r.encoding)   #encoding为ISO-8859-1
    print(r.apparent_encoding)  #apparent_encoding分析内容后,找到可能编码(此为utf-8编码)
    r.encoding=r.apparent_encoding  #避免乱码
    print(r.text)

在这里插入图片描述

2.通用代码框架

Requests 库异常

requests.ConnectionError

网络连接错误异常,如 DNS 查询失败、拒绝连接等

requests.HTTPError

HTTP 错误异常

requests.URLRequired

URL 缺失异常

requests.TooManyRedirects

超过最大重定向次数,产生重定向异常

requests.ConnectTimeout

连接远程服务器超时异常

requests.Timeout

请求 URL 超时,产生超时异常

Response 异常:

r.raise_for_status()

如果不是 200,产生异常 requests.HTTPError

r.raise_for_status() 在方法内部判断 r.status_code 是否等于 200 ,不需要增加额外的 if 语句,该语句便于利用 Python 的 try‐except 机制进行异常处理

# -*- coding:utf-8 -*-
"""
通用代码框架
"""

import requests

def getHTMLtext(url):
    try:
        r = requests.get(url)
        r.raise_for_status() #如果状态不是200,引发HTTPError异常
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "产生异常"

if __name__ == "__main__":
    url = "http://www.baidu.com"
    print(getHTMLtext(url))

3.HTTP协议和Requests库方法

Hypertext Transfer Protocol

在这里插入图片描述
在这里插入图片描述

HTTP 协议对资源的操作

GET

请求获取 URL 位置的资源

HEAD

请求获取 URL 位置资源的响应消息报告,即获得该资源的头部信息

POST

请求向 URL 位置的资源后附加新的数据

PUT

请求向 URL 位置存储一个资源,覆盖原 URL 位置的资源

PATCH

请求局部更新 URL 位置的资源,即改变该处资源的部分内容

DELETE

请求删除 URL 位置存储的资源

这些方法与 requests 库里的常用方法作用一致

在这里插入图片描述

理解 patch 和 put 区别

假设 URL 位置有一组数据 UserInfo,包括 UserID、UserName 等 20 个字段

需求:用户修改了 UserName,其他不变

• 采用 PATCH,仅向 URL 提交 UserName 的局部更新请求

• 采用 PUT,必须将所有 20 个字段一并提交到 URL,未提交字段被删除

PATCH 的最主要好处:节省网络带宽

方法简介:

head()

# -*- coding:utf-8 -*-

import requests

r = requests.head('http://httpbin.org/get')
print(r.headers)
print(r.text)	#没有反应,因为这里只爬取了头部信息

post()

# -*- coding:utf-8 -*-

import requests

payload = {
    
    'key1': 'value1', 'key2': 'value2'}	#创建一个字典
r = requests.post('http://httpbin.org/post',data = payload)	#附加新的数据
#向URL POST一个字典 自动编码为form(表单)
print(r.text)
# -*- coding:utf-8 -*-

import requests

r = requests.post('http://httpbin.org/post', data = 'ABC')
#向URL POST一个字符串 自动编码为data
print(r.text)

put()

# -*- coding:utf-8 -*-

import requests

payload = {
    
    'key1': 'value1', 'key2': 'value2'}
r = requests.put('http://httpbin.org/put', data = payload)
print(r.text)

4.requests库主要方法解析

复习:

requests.request()

构造一个请求,支撑以下各方法的基础方法

requests.get()

获取 HTML 网页的主要方法,对应于 HTTP 的 GET

requests.head()

获取 HTML 网页头信息的方法,对应于 HTTP 的 HEAD

requests.post()

向 HTML 网页提交 POST 请求的方法,对应于 HTTP 的 POST

requests.put()

向 HTML 网页提交 PUT 请求的方法,对应于 HTTP 的 PUT

requests.patch()

向 HTML 网页提交局部修改请求,对应于 HTTP 的 PATCH

requests.delete()

向 HTML 页面提交删除请求,对应于 HTTP 的 DELETE

a.重中之重:requests.request

在这里插入图片描述
在这里插入图片描述

十三个控制参数:

params : 字典或字节序列,作为参数增加到 url 中

data : 字典、字节序列或文件对象,作为 Request 的内容

json : JSON 格式的数据,作为 Request 的内容

headers : 字典,HTTP 定制头

cookies : 字典或 CookieJar,Request 中的 cookie

auth : 元组,支持 HTTP 认证功能

files : 字典类型,传输文件

timeout : 设定超时时间,秒为单位

proxies : 字典类型,设定访问代理服务器,可以增加登录认证

allow_redirects : True/False,默认为 True,重定向开关

stream : True/False,默认为 True,获取内容立即下载开关

verify : True/False,默认为 True,认证 SSL 证书开关

cert : 本地SSL证书路径

params : 字典或字节序列,作为参数增加到 url 中

# -*- coding:utf-8 -*-

import requests

kv = {
    
    'key1': 'value1', 'key2': 'value2'}
r = requests.request('GET', 'http://python123.io/ws', params=kv)
print(r.url)
http://python123.io/ws?key1=value1&key2=value2

data : 字典、字节序列或文件对象,作为Request的内容

# -*- coding:utf-8 -*-

import requests

kv = {
    
    'key1': 'value1', 'key2': 'value2'}
r = requests.request('POST', 'http://python123.io/ws', data=kv)
body = '主体内容'
r = requests.request('POST', 'http://python123.io/ws', data=body)
#放在URL链接对应位置的地方,作为数据存储

json : JSON格式的数据,作为 Request 的内容

# -*- coding:utf-8 -*-

import requests

kv = {
    
    'key1': 'value1'}
r = requests.request('POST', 'http://python123.io/ws', json=kv)

headers : 字典,HTTP 定制头

# -*- coding:utf-8 -*-

import requests

hd = {
    
    'user‐agent': 'Chrome/10'}
r = requests.request('POST', 'http://python123.io/ws', headers=hd)
#将header里的'user‐agent'替换为'Chrome/10'

cookies : 字典或 CookieJar,Request 中的 cookie

auth : 元组,支持 HTTP 认证功能

files : 字典类型,传输文件

# -*- coding:utf-8 -*-

import requests

fs = {
    
    'file': open('data.xls', 'rb')}
r = requests.request('POST', 'http://python123.io/ws', files=fs)

timeout : 设定超时时间,秒为单位

# -*- coding:utf-8 -*-

import requests

r = requests.request('GET', 'http://www.baidu.com', timeout=10)

proxies : 字典类型,设定访问代理服务器,可以增加登录认证

# -*- coding:utf-8 -*-

import requests

pxs = {
    
     'http': 'http://user:[email protected]:1234'
'https': 'https://10.10.10.1:4321' }
r = requests.request('GET', 'http://www.baidu.com', proxies=pxs)
#有效隐藏用户爬取网页源的信息,防止逆追踪

allow_redirects : True/False,默认为 True,重定向开关

stream : True/False,默认为 True,获取内容立即下载开关

verify : True/False,默认为 True,认证 SSL 证书开关

cert : 本地 SSL 证书路径

b.其他方法

与 requests.requests 不同,其他函数有些参数是常用参数,所以作为显式定义量放在参数表内,剩余的就是 13 个访问参数中放在剩余的可选参数字段里(**kwargs)

requests.get(url, params=None, **kwargs)	#获取网页信息,返回response类

requests.head(url, **kwargs)	#获取网页头信息

requests.post(url, data=None, json=None, **kwargs)	#附加新的数据请求

requests.put(url, data=None, **kwargs)	#全部修改(覆盖)请求

requests.patch(url, data=None, **kwargs)	#局部修改

requests.patch(url, data=None, **kwargs)	#提交删除请求

四、网络爬虫规则与robots协议

在这里插入图片描述

  • 网络爬虫带来的问题:

性能骚扰、法律风险、隐私泄露

  • 网络爬虫的限制

  • 来源审查:判断 User-Agent 进行限制

​ 检查来访 HTTP 协议头的 User-Agent 域,只影响浏览器或友好爬虫的访问

  • 发布公告:Robots 协议

​ 告知所有爬虫网站的爬取策略,要求爬虫遵守

  • Robots 协议语法:
# *代表所有,/代表根目录

User-Agent: *
#表示所有的爬虫
Disallow: /
#表示不允许爬虫访问资源的目录
  • 例子:
User‐agent: *
Disallow: /?*
Disallow: /pop/*.html
Disallow: /pinpai/*.html?*
User‐agent: EtaoSpider
Disallow: /
User‐agent: HuihuiSpider
Disallow: /
User‐agent: GwdangSpider
Disallow: /
User‐agent: WochachaSpider
Disallow: /
Disallow: /?*
#表示所有爬虫都不能访问以?开头的路径

User‐agent: EtaoSpider
Disallow: /
#表示这个网络爬虫不允许爬取任何资源(此为恶意爬虫)

http://www.baidu.com/robots.txt

http://news.sina.com.cn/robots.txt

http://www.qq.com/robots.txt

http://news.qq.com/robots.txt

http://www.moe.edu.cn/robots.txt (无robots协议)

  • 对 Robots 协议的理解

在这里插入图片描述

类人行为就是指,比如说一个小时爬取一次数据,就和人访问服务器的行为类似,可以不参考Robots协议

五、Requests库实战

1.京东商品页面的爬取
# -*- coding:utf-8 -*-

import requests
url = "https://item.jd.com/2967929.html"
try:
    r = requests.get(url)
    r.raise_for_status()	#返回为200是不会产生异常的
    r.encoding = r.apparent_encoding
    print(r.text[:1000])
except:
    print("爬取失败")
2.亚马逊商品页面的爬取
>>> import requests
>>> r = requests.get("https://www.amazon.cn/gp/product/B01M8L5Z3Y")
>>> r.status_code
503
>>> r.encoding = r.apparent_encoding
'ISO-8859-1'
>>> r.request.headers
{
    
    'User-Agent': 'python-requests/2.22.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

爬虫忠实告诉服务器,这次访问是 python 一个库的程序产生的,亚马逊可以让这个访问不支持,所以应该让程序模拟一个浏览器发送爬虫请求。

# -*- coding:utf-8 -*-

import requests

url = "https://www.amazon.cn/gp/product/B01M8L5Z3Y"
try:
    kv = {
    
    'user-agent': 'Mozilla/5.0'}	#表示标准的浏览器身份标识字段
    r = requests.get(url, headers = kv)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.request.headers)
    print(r.text[1000:2000])
except:
    print("爬取失败")
3.百度 / 360搜索关键字提交

在这里插入图片描述

>>> import requests
>>> kv = {
    
    'wd': 'python'}
>>> r = requests.get("http://www.baidu.com/s", params = kv)
>>> r.status_code
200
>>> r.request.url
https://www.baidu.com/s?wd=python&p_tk=32265Tk4jnPUNRUky3cmO1QqjFQiddo35lfkGdrZ1lY9q7bOAR5tM9UZZRgnfXdl3hQafPRVc2hkJgoUsl22KfuHAgyRZTuQK2NKPU%2FOObY8gw8%3D&p_timestamp=1576427126&p_signature=1aa1e3bf761cd8b11e9d17131efcfb2c
# -*- coding:utf-8 -*-

import requests

#百度搜索
kv = {
    
    'wd': '华中科技大学'}
try:
    r = requests.get("http://www.baidu.com/s", params = kv)
    print(r.request.url)
    r.raise_for_status()
    print(len(r.text))
except:
    print("爬取失败")
# -*- coding:utf-8 -*-

import requests

#360搜索
keyword = input("请输入你想搜索的内容")	#搜索
kv = {
    
    'q': keyword}
try:
    r = requests.get("http://www.so.com/s", params = kv)
    print(r.request.url)
    r.raise_for_status()
    print(len(r.text))
except:
    print("爬取失败")
https://www.so.com/s?q=%E5%8D%8E%E4%B8%AD%E7%A7%91%E6%8A%80%E5%A4%A7%E5%AD%A6
4.网络图片的爬取和存储

在这里插入图片描述

在这里插入图片描述

>>> import requests
>>> path = "D:/abc.jpg"
>>> url = "http://image.ngchina.com.cn/2019/1213/20191213060809562.jpg"
>>> r =  requests.get(url)
>>> r.status_code
200
>>> with open(path, 'wb') as f:
	f.write(r.content)

	
302586
>>> f.close
<built-in method close of _io.BufferedWriter object at 0x00000210E1445518>
# -*- coding:utf-8 -*-

import requests
import os

url = "http://image.ngchina.com.cn/2019/1213/20191213060809562.jpg"
root = "C://Users//魏靖旻//Desktop//python//爬虫//"
path =  root + url.split('/')[-1]	#截取文件本来的名字
try:
    if not os.path.exists(root):	#当前目录不存在,则建立
        os.mkdir(root)
    if not os.path.exists(path):
        r = requests.get(url)
        r.raise_for_status()
        with open(path, 'wb') as f:
            f.write(r.content)	#以二进制形式把response写入文件
            f.close()
            print("文件爬取成功")
    else:
        print("文件已存在")
except:
    print("爬取失败")

在这里插入图片描述
在这里插入图片描述

# -*- coding:utf-8 -*-

import requests
import os

url = "https://mmbiz.qpic.cn/mmbiz_png/CiaO42KaqJZ0csKNSS73ql6O1UcJA7rRkRzsIZiczL7xKCDNwXI1JEeibrZh17SDpaiavGgJyjJSoKIkjOl0BD5Iiaw/640?wx_fmt=png&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1"
root = "C://Users//魏靖旻//Desktop//python//爬虫//"
path =  root + "小魏小民的帅照.jpg"	#建立文件名字
try:
    if not os.path.exists(root):	#当前目录不存在,则建立
        os.mkdir(root)
    if not os.path.exists(path):
        r = requests.get(url)
        r.raise_for_status()
        with open(path, 'wb') as f:
            f.write(r.content)	#以二进制形式把response写入文件
            f.close()
            print("文件爬取成功")
    else:
        print("文件已存在")
except:
    print("爬取失败")
5.IP地址归属地的自动查询

在这里插入图片描述

>>> import requests
>>> url = "http://m.ip138.com/ip.asp?ip="
>>> kv = {
    
    'user-agent': 'Mozilla/5.0'}
>>> r = requests.get(url + '202.114.0.0', headers = kv)
>>> r.status_code
200
>>> r.text[-500:]
'value="查询" class="form-btn" />\r\n\t\t\t\t\t</form>\r\n\t\t\t\t</div>\r\n\t\t\t\t<div class="query-hd">ip138.com IP查询(搜索IP地址的地理位置)</div>\r\n\t\t\t\t<h1 class="query">您查询的IP:202.114.0.0</h1><p class="result">本站主数据:湖北省武汉市 华中科技大学 教育网</p><p class="result">参考数据一:湖北省武汉市 华中科技大学</p>\r\n\r\n\t\t\t</div>\r\n\t\t</div>\r\n\r\n\t\t<div class="footer">\r\n\t\t\t<a href="http://www.miitbeian.gov.cn/" rel="nofollow" target="_blank">沪ICP备10013467号-1</a>\r\n\t\t</div>\r\n\t</div>\r\n\r\n\t<script type="text/javascript" src="/script/common.js"></script></body>\r\n</html>\r\n'

在这里插入图片描述

# -*- coding:utf-8 -*-

import requests

url = "http://m.ip138.com/ip.asp?ip="	#解析网站,发现ip查询的实质API
kv = {
    
    'user-agent': 'Mozilla/5.0'}
org = input("请输入域名\n",)	#202.114.0.0

try:
    r = requests.get(url + org, headers = kv)	#相当于查询操作
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[-500:])
except:
    print("爬取失败")

猜你喜欢

转载自blog.csdn.net/weixin_44979150/article/details/123428641