介绍了 2 种反爬的方式:
请求头
代理 IP
一, 反爬手段 1-- 向请求头中添加 User-Agent:
请求头, 响应头:
1. 响应头: response_header
响应头 response_header, 可以通过 response 对象. headers, 获取得到.
response.headers, 得到的是响应头信息
- def load():
- # 1. 目标网页 URL 地址
- URL = "http://www.baidu.com/"
- # 2. 发送网络请求:
- # 返回 response 对象, 使用 response 对象接收服务器返回的数据
- response = urllib.request.urlopen(URL)
- # 得到响应头信息
- print(response.headers)
- load()
结果为:
- Bdpagetype: 1
- Bdqid: 0xbfd0e4790001890b
- Cache-Control: private
- Content-Type: text/html
- Cxy_all: baidu+739fcb9dd92b830634cd2f957c8e6f67
- Date: Fri, 03 May 2019 15:30:05 GMT
- Expires: Fri, 03 May 2019 15:29:21 GMT
- P3p: CP="OTI DSP COR IVA OUR IND COM"
- Server: BWS/1.1
- Set-Cookie: BAIDUID=2D1BE12D094679CAE43187C509B76E5D:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
- Set-Cookie: BIDUPSID=2D1BE12D094679CAE43187C509B76E5D; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
- Set-Cookie: PSTM=1556897405; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
- Set-Cookie: delPer=0; path=/; domain=.baidu.com
- Set-Cookie: BDSVRTM=0; path=/
- Set-Cookie: BD_HOME=0; path=/
- Set-Cookie: H_PS_PSSID=28884_1454_21091_28724_28963_28837_28584; path=/; domain=.baidu.com
- Vary: Accept-Encoding
- X-Ua-Compatible: IE=Edge,Chrome=1
- Connection: close
- Transfer-Encoding: chunked
和浏览器中 f12,network 中的 Response Headers 显示的信息对比, 基本一致
2. 请求头: request_header(重点)
User-Agent 是在模拟真实用户发送网络请求
(1)目的: 我们要向请求头里面, 添加 User-Agent 信息, 这样就可以干掉一部分的反爬手段.
(2)request = urllib.request.Request(目标网页 URL 地址)
-- 创建 request 对象
要想获取请求头 request_header, 我们需要先创建 request 对象, 然后通过 request 对象获取请求头.
注意: Request()首字母必须大写
(3)request.headers, 就可以得到请求头的信息.
(4)request.add_header('User_Agent', 'xxx')
-- 向请求头中添加'User-Agent'信息
使用爬虫, 最开始时, 请求头 request_header 中是空的, 为了模拟真实用户, 需要向请求头 request_header 中添加信息; 必须先创建 request 对象之后, 再向 request_header 中添加请求头信息.
xxx 就是冒号 (:) 后面的那些
(5)response = urllib.request.urlopen(request)
发送网络请求, 这个方法的参数, 既可以是 URL 地址, 也可以是 request 对象.
(6)request.get_header('User-agent')
-- 获取请求头信息的第二种方式
注意:
a. 这里的参数是'User-agent', 只有 U 大写, A 小写;
request.add_header()中,"User-Agent",U 和 A 都大写.
b. request.get_header(), 这个方法只能得到请求头的一部分信息
如: request.get_header('User-agent')只会得到 User-Agent 信息
而 request.headers, 得到的是请求头的全部信息
(7)request.get_full_url()
可以得到完整的 URL
(8)添加 User-Agent 信息, 爬取百度首页
- import urllib.request
- import urllib.parse
- #爬取百度首页 https://www.baidu.com/
- def load():
- #1. 目标网页 URL
- URL = "https://www.baidu.com/"
- #2. 向请求头中添加 User-Agent 信息
- #2.1 创建 request 对象, 参数为目标网页的 URL
- request = urllib.request.Request(URL)
- #打印最开始时请求头的 User-Agent
- print(request.get_header('User-agent'))
- #2.2 向请求头中添加 User-Agent 信息
- request.add_headers('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ApplewebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36')
- #再次打印请求头的 User-Agent
- print(request.get_header('User-agent'))
- #3. 发送网络请求, response 接收返回数据
- #参数填写添加 User-Agent 信息之后的 request 对象
- response = urllib.request.urlopen(request)
- load()
结果:
可以看到, 一开始时, User-Agent 的信息为 None, 添加之后, 为我们添加的信息
注意: 发送网络请求的代码, urllib.request.urlopen(request)参数填写 request 对象, 而非 URL;
如果填 URL, 则发送请求的请求头没有添加我们添加的 User-Agent 信息, 还是为空 None.
1.5 使用多个 User-Agent:
(1)由于爬虫会在极短的时间内(一秒钟), 访问服务器很多次(几百次). 所以, 如果只使用一个 User-Agent, 很容易被服务器识别为爬虫.
(2)反爬手段 2.5: 使用多个 User-Agent
百度搜索: User-Agent 大全
使用 fake User-Agent(包含 250 个 User-Agent)
User-Agent 池(推荐)
-- 这样, 每次发送网络请求的浏览器信息和个人信息都不一样, 就可以干掉反爬了
(3)思路: 设置一个 User-Agent 的列表, 每次从中随机选取一个 User-Agent
(4)代码:
- import urllib.request
- import urllib.parse
- import random
- # 爬取百度首页 https://www.baidu.com/
- def load():
- #1. 目标网页 URL
- URL = "https://www.baidu.com/"
- #2. 向请求头中添加 User-Agent 信息
- #2.1 设置 User-Agent 池:
- user_agent_list = ['Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
- 'Opera/8.0 (Windows NT 5.1; U; en)',
- 'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
- 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
- 'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10;',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
- 'Opera/8.0 (Windows NT 5.1; U; en)',
- 'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
- 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
- 'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
- ]
- #2.2 从 User-Agent 池中随机选择一个 User-Agent
- choose_user_agent = random.choice(user_agent_list)
- #2.2 创建 request 对象, 参数为目标网页的 URL
- request = urllib.request.Request(URL)
- #打印最开始时请求头的 User-Agent
- print(request.get_header('User-agent'))
- #2.2 向请求头中添加 User-Agent 信息
- request.add_headers('User-Agent', choose_user_agent)
- #再次打印请求头的 User-Agent
- print(request.get_header('User-agent'))
- #3. 发送网络请求, response 接收返回数据
- #参数填写添加 User-Agent 信息之后的 request 对象
- response = urllib.request.urlopen(request)
- load()
二, 反爬手段 2-- 代理 IP:
理论:
(1)IP 分为免费 IP 和付费 IP:
1.1 免费 IP: 时效性差, 错误率高
1.2 付费 IP: 时效性强, 错误率低, 但是也有失效的 IP
(2)IP 的三种叫法:
2.1 透明 IP: 对方知道我自己的真实 IP
2.2 匿名 IP: 对方不知道我自己的真实 IP, 但是知道我使用了代理 IP
2.3 高匿名 IP: 对方不知道我自己的真实 IP, 也不知道我使用了代理 IP
注: 由图可以发现, 代理 IP 分为 HTTP 和 HTTPS, 可以根据自己的需求, 找自己要的类型 IP
(3)IP 分为免费 IP 写法和付费 IP 写法
(4)发送网络请求, 需要使用我们自己添加的代理 IP. 看上面的爬虫代码, 可以发现: 在发送网络请求之前, 只涉及到两个东西, 一个是 request 对象, 另一个是 urllib.request.urlopen()方法.
查看 request 和 urlopen()
通过查看 request 对象和 urlopen()方法源码, 发现这两个对象, 都没有提供加入代理 IP 的位置.
所以, 我们应该在哪里加入, 我们自己想要伪装的代理 IP 呢???
查看 urlopen()方法代码
发现: 该方法的本质是创建了一个 opener 对象, 返回的是 opener.open()
而 opener 对象, 又是通过 build_opener()一个 handler 处理器对象得来的
所以说, 如果能在 handler 对象中加入我们要伪装的代理 IP, 然后用该对象创建 opener 对象, 再调用 open()方法, 就可以达到我们的目的: 伪装使用代理 IP 向服务器发送网络请求.
总结一下:
urlopen()和 request 对象都没有添加 IP 的方法
urlopen()的底层本质上是: 先创建 handler 对象, 然后创建 opener 对象, 再用 opener.open()的方法发送网络请求, 爬取数据.
我们需要创建一个能够添加代理 IP 的 handler 处理器 --proxyhandler, 然后利用它创建 opener 对象, 最后发送请求.
代码:
- import urllib.request
- import urllib.parse
- import string
- import random
- # 使用添加的 User-Agent 和代理 IP, 爬取搜狗搜索的首页
- def load():
- # 1. 目标网页 URL:
- URL = 'https://www.sogou.com/'
- # 2. 向请求头添加 User-Agent
- # 2.1 创建 request 对象
- request = urllib.request.Request(URL)
- # 2.2 设置 User-Agent 池
- User_Agent_List = [
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
- 'Opera/8.0 (Windows NT 5.1; U; en)',
- 'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
- 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
- 'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10;',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60',
- 'Opera/8.0 (Windows NT 5.1; U; en)',
- 'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
- 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
- 'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
- ]
- # 2.3 每次请求随机选择一个 User-Agent
- choose_User_Agent = random.choice(User_Agent_List)
- # 2.4 向请求头信息中, 添加 User-Agent
- request.add_header('User-Agent', choose_User_Agent)
- # 3. 添加代理 IP
- # 3.1 设置代理 IP
- proxy_ip = {'https': '116.52.13.90:808'}
- # 3.2 创建 handler 处理器对象
- proxy_handler = urllib.request.ProxyHandler(proxy_ip)
- # 3.3 创建 opener 对象(因为真正发送网络请求的是 opener 而非 handler)
- opener = urllib.request.build_opener(proxy_handler)
- # 3.4 调用 open 方法, 发送网络请求
- response = opener.open(request)
- # 4. 发送网络请求, 使用 response 对象接收数据
- #因为 3.4 中已经做了
- # 5. 读取 response 对象里面的数据, 转码为字符串格式
- str_data = response.read().decode('utf-8')
- # 6. 保存数据
- with open('sougou.com02.html', 'w', encoding='utf-8') as f:
- f.write(str_data)
- load()
注意:
(1)代理 IP 的设置格式:
1.1 使用字典放置
1.2 键 key: 相应的代理 IP 的类型(http 或者 https)
1.3 值 value: 代理 IP: 端口号
1.4 键 http/https; 值 IP 地址 + 端口号, 均使用字符串格式
- eg:
- proxy = {
- 'http': "115.223.69.54:8010", "https": "116.209.52.248:9999"
- }
(2)opener.open()中的参数, 既可以是目标网页的 URL 也可以是 request 对象. 这里由于, 我们要使用添加的 User-Agent, 所以参数用 request 对象.
来源: http://www.bubuko.com/infodetail-3046108.html