哈尔滨网站设计哪家好,哪些企业需要做网站建设,桐乡建设规划局网站,福田网站建设推荐文章目录 一、代理的设置1.1 urllib 的代理设置1.2 requests 的代理设置1.3 httpx 的代理设置1.4 aiohttp 的代理设置1.4 Selenium 的代理设置1.6 Playwright 的代理设置 二、代理池的构建和维护2.1 代理池的模块构成2.2 代理池的实现 网站为了避免爬虫采集数据可能会采取一些反… 文章目录 一、代理的设置1.1 urllib 的代理设置1.2 requests 的代理设置1.3 httpx 的代理设置1.4 aiohttp 的代理设置1.4 Selenium 的代理设置1.6 Playwright 的代理设置 二、代理池的构建和维护2.1 代理池的模块构成2.2 代理池的实现 网站为了避免爬虫采集数据可能会采取一些反爬虫的措施例如服务器会检测某个 IP 在单位时间内的请求次数如果这个次数超过了指定的阈值就直接拒绝服务器并返回一些错误信息这种情况称为 封IP
封IP 的流程是开始可以正常运行正常爬取数据一段时间过后出现错误比如返回 403 Forbidden这时打开网页可能会看到 “您的 IP 访问频率太高” 这样的提示或者跳出一个验证码让我们识别通过之后才可以正常访问但是过一会儿又会变成这样
代理通过将 IP 伪装起来让服务器识别不出是由我们本机发起的请求就可以成功防止封 IP了
一、代理的设置
代理是 IP 地址和端口的组合格式是 ip:port如果代理需要访问认证则还需要额外的用户名和密码两个信息
1.1 urllib 的代理设置
首先我们以最基础的 urllib 为例来看一下代理的设置方法代码如下
from urllib.error import URLError
from urllib.request import ProxyHandler, build_openerproxy 127.0.0.1:9743
proxy_handler ProxyHandler({http: http:// proxy,https: https:// proxy
})
opener build_opener(proxy_handler)
try:response opener.open(http://httpbin.org/get)print(response.read().decode(utf-8))
except URLError as e:print(e.reason)运行结果如下
{args: {}, headers: {Accept-Encoding: identity, Connection: close, Host: httpbin.org, User-Agent: Python-urllib/3.6}, origin: 106.185.45.153, url: http://httpbin.org/get
}这里我们需要借助 ProxyHandler 设置代理参数是字典类型键名为协议类型键值是代理。注意此处代理前面需要加上协议即 http 或者 https。当请求的链接是 http 协议的时候ProxyHandler 会调用 http 代理。当请求的链接是 https 协议的时候会调用 https 代理。此处生效的代理是http://127.0.0.1:9743。
创建完 ProxyHandler 对象之后我们需要利用 build_opener 方法传入该对象来创建一个 Opener这样就相当于此 Opener 已经设置好代理了。接下来直接调用 Opener 对象的 open 方法即可访问我们所想要的链接。
运行输出结果是一个 JSON它有一个字段 origin标明了客户端的 IP。验证一下此处的 IP 确实为代理的 IP并不是真实的 IP。这样我们就成功设置好代理并可以隐藏真实 IP 了。
如果遇到需要认证的代理我们可以用如下的方法设置
from urllib.error import URLError
from urllib.request import ProxyHandler, build_openerproxy username:password127.0.0.1:9743
proxy_handler ProxyHandler({http: http:// proxy,https: https:// proxy
})
opener build_opener(proxy_handler)
try:response opener.open(http://httpbin.org/get)print(response.read().decode(utf-8))
except URLError as e:print(e.reason)这里改变的只是 proxy 变量只需要在代理前面加入代理认证的用户名密码即可其中 username 就是用户名password 为密码例如 username 为 foo密码为 bar那么代理就是 foo:bar127.0.0.1:9743。
如果代理是 SOCKS5 类型那么可以用如下方式设置代理
import socks
import socket
from urllib import request
from urllib.error import URLErrorsocks.set_default_proxy(socks.SOCKS5, 127.0.0.1, 9742)
socket.socket socks.socksocket
try:response request.urlopen(http://httpbin.org/get)print(response.read().decode(utf-8))
except URLError as e:print(e.reason)此处需要一个 socks 模块可以通过如下命令安装
pip3 install PySocks本地我有一个 SOCKS5 代理运行在 9742 端口运行成功之后和上文 HTTP 代理输出结果是一样的
{args: {}, headers: {Accept-Encoding: identity, Connection: close, Host: httpbin.org, User-Agent: Python-urllib/3.6}, origin: 106.185.45.153, url: http://httpbin.org/get
}结果的 origin 字段同样为代理的 IP。现在代理设置成功。
1.2 requests 的代理设置
对于 requests 来说代理设置更加简单我们只需要传入 proxies 参数即可。
还是以上例中的代理为例我们来看下 requests 的代理的设置
import requestsproxy 127.0.0.1:9743
proxies {http: http:// proxy,https: https:// proxy,
}
try:response requests.get(http://httpbin.org/get, proxiesproxies)print(response.text)
except requests.exceptions.ConnectionError as e:print(Error, e.args)运行结果
{args: {}, headers: {Accept: */*, Accept-Encoding: gzip, deflate, Connection: close, Host: httpbin.org, User-Agent: python-requests/2.18.1}, origin: 106.185.45.153, url: http://httpbin.org/get
}可以发现requests 的代理设置比 urllib 简单很多它只需要构造代理字典然后通过 proxies 参数即可而不需要重新构建 Opener。
其运行结果的 origin 也是代理的 IP这证明代理已经设置成功。
如果代理需要认证同样在代理的前面加上用户名密码即可代理的写法就变成如下所示
proxy username:password127.0.0.1:9743和 urllib 一样这里只需要将 username 和 password 替换即可。
如果需要使用 SOCKS5 代理则可以使用如下方式来设置
import requestsproxy 127.0.0.1:9742
proxies {http: socks5:// proxy,https: socks5:// proxy
}
try:response requests.get(http://httpbin.org/get, proxiesproxies)print(response.text)
except requests.exceptions.ConnectionError as e:print(Error, e.args)在这里我们需要额外安装一个模块这个模块叫作requests[socks]命令如下所示
pip3 install requests[socks]运行结果是完全相同的
{args: {}, headers: {Accept: */*, Accept-Encoding: gzip, deflate, Connection: close, Host: httpbin.org, User-Agent: python-requests/2.18.1}, origin: 106.185.45.153, url: http://httpbin.org/get
}另外还有一种设置方式和 urllib 中的方法相同使用 socks 模块也需要像上文一样安装 socks 库。这种设置方法如下所示
import requests
import socks
import socketsocks.set_default_proxy(socks.SOCKS5, 127.0.0.1, 9742)
socket.socket socks.socksocket
try:response requests.get(http://httpbin.org/get)print(response.text)
except requests.exceptions.ConnectionError as e:print(Error, e.args)使用这种方法也可以设置 SOCKS5 代理运行结果完全相同。相比第一种方法此方法是全局设置。我们可以在不同情况下选用不同的方法。
1.3 httpx 的代理设置
httpx 的用法本身就与 requests 的非常相似所以也是通过 proxies 参数设置的代理不同之处在于 proxies 参数的键名不能再是 http 和 https需要改为 \http:// 和 \https://
设置 HTTP 代理的方式如下
import httpxproxy 127.0.0.1:7890
proxies {http://: http:// proxy,https://: http:// proxy,
}with httpx.Client(proxiesproxies) as client:response client.get(https://www.httpbin.org/get)print(response.text)对于需要认证的代理也是在代理地址的前面加上用户名和密码在使用的使用替换 usename 和 password 字段
proxy username:password127.0.0.1:7890对于 SOCKS 代理需要安装 httpx-socks[asyncio] 库安装方法如下
pip3 install httpx-socks[asyncio]与此同时我们需要设置同步模式和异步模式同步模式的设置方法如下
import httpx
from httpx_socks import SyncProxyTransporttransport SyncProxyTransport.from_url(sock5://127.0.0.1:7891)with httpx.Client(transporttransport) as client:response client.get(https://www.httpbin.org/get)print(response.text)异步模式的设置方法如下
import httpx
import asyncio
from httpx_socks import AsyncProxyTransporttransport AsyncProxyTransport.from_url(sock5://127.0.0.1:7891)async def main():async with httpx.AsyncClient(transporttransport) as client:response await client.get(https://www.httpbin.org/get)print(response.text)if __name__ __main__:asyncio.get_event_loop().run_until_complete(main())和同步模式不同此时我们用的 Transport 对象是 AsyncProxyTransport 而不是 SyncProxyTransport同时需要将 Client 对象更改为 AsyncClient 对象其他的和同步模式一样运行结果也是一样的
1.4 aiohttp 的代理设置
对于 aiohttp可以通过 proxy 参数直接设置代理http 代理的设置方式如下
import asyncio
import aiohttpproxy http://127.0.0.1:7890async def main():async with aiohttp.ClientSession() as session:async with session.get(https://www.httpbin.org/get, proxyproxy) as response:print(await response.text())if __name__ __main__:asyncio.get_event_loop().run_until_complete(main())如果需要代理认证就把代理地址改一下
proxy http://username:password127.0.0.1:7890对于 SOCKS 代理需要安装一个支持库 aiohttp-socks 安装命令如下
pip3 install aiohttp-socks可以借助这个库的 ProxyConnector 方法来设置 SOCKS 代理代码如下
import asyncio
import aiohttp
from aiohttp_sock5 import ProxyConnectorconnector ProxyConnector.from_url(socks5://127.0.0.1:7890)
async def main():async with aiohttp.ClientSession(connectorconnector) as session:async with session.get(http://www.httpbin.org/get) as response:print(await response.text())if __name__ __main__:asyncio.get_event_loop().run_until_complete(main())运行结果和之前一样
1.4 Selenium 的代理设置
Selenium 同样也可以设置代理对于 Chrome 来说用 Selenium 设置代理的方法也非常简单对于无认证的代理设置方法如下所示
from selenium import webdriverproxy 127.0.0.1:9743
chrome_options webdriver.ChromeOptions()
chrome_options.add_argument(--proxy-serverhttp:// proxy)
browser webdriver.Chrome(chrome_optionschrome_options)
browser.get(http://httpbin.org/get)在这里我们通过 ChromeOptions 来设置代理在创建 Chrome 对象的时候用 chrome_options 参数传递即可。
运行代码之后便会弹出一个 Chrome 浏览器我们访问目标链接之后输出结果如下所示
{args: {}, headers: {Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,image/apng,*/*;q0.8, Accept-Encoding: gzip, deflate, Accept-Language: zh-CN,zh;q0.8, Connection: close, Host: httpbin.org, Upgrade-Insecure-Requests: 1, User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36}, origin: 106.185.45.153, url: http://httpbin.org/get
}代理设置成功origin 同样为代理 IP 的地址。如果代理是认证代理则设置方法相对比较麻烦设置方法如下所示
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import zipfileip 127.0.0.1
port 7890
username foo
password barmanifest_json {version:1.0.0,manifest_version: 2,name:Chrome Proxy,permissions: [proxy,tabs,unlimitedStorage,storage,all_urls,webRequest,webRequestBlocking],background: {scripts: [background.js]}
}
background_js
var config {mode: fixed_servers,rules: {singleProxy: {scheme: http,host: %(ip) s,port: %(port) s}}}chrome.proxy.settings.set({value: config, scope: regular}, function() {});function callbackFn(details) {return {authCredentials: {username: %(username) s,password: %(password) s}}
}chrome.webRequest.onAuthRequired.addListener(callbackFn,{urls: [all_urls]},[blocking]
)% {ip: ip, port: port, username: username, password: password}plugin_file proxy_auth_plugin.zip
with zipfile.ZipFile(plugin_file, w) as zp:zp.writestr(manifest.json, manifest_json)zp.writestr(background.js, background_js)
chrome_options Options()
chrome_options.add_argument(--start-maximized)
chrome_options.add_extension(plugin_file)
browser webdriver.Chrome(chrome_optionschrome_options)
browser.get(http://httpbin.org/get)这里需要在本地创建一个 manifest.json 配置文件和 background.js 脚本来设置认证代理。运行代码之后本地会生成一个 proxy_auth_plugin.zip 文件来保存当前配置。
得到运行结果和上面一样origin 字段为客户端的 IP证明代理设置成功SOCKS 代理的设置方式也比较简单把对应的协议修改为 socks5 即可如无密码认证的代理设置方法为
from selenium import webdriverproxy 127.0.0.1:7890
chrome_options webdriver.ChromeOptions()
chrome_options.add_argument(--proxy-serversocks5:// proxy)
browser webdriver.Chrome(chrome_optionschrome_options)
browser.get(http://httpbin.org/get)运行结果和上面一样
1.6 Playwright 的代理设置
相对 Selenium 和 PyppeteerPlaywright 的代理设置更加的方便因为其预留了一个 proxy 参数在启动的时候就可以设置。
对于 HTTP / SOCKS 代理来说可以这样设置
from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser p.Chromium.launch(proxy:{server: http://127.0.0.1:7890, # server: socks5://127.0.0.1:7890, })page browser.new_page()page.goto(http://www.httpbin.org/get)print(page.content())browser.close()二、代理池的构建和维护
2.1 代理池的模块构成
基本模块分为 4 块存储模块、获取模块、检测模块、接口模块。
![[9-1.jpg]] 存储模块负责存储抓取下来的代理。首先要保证代理不重复要标识代理的可用情况还要动态实时处理每个代理所以一种比较高效和方便的存储方式就是使用 Redis 的 Sorted Set即有序集合。 获取模块需要定时在各大代理网站抓取代理。代理可以是免费公开代理也可以是付费代理代理的形式都是 IP 加端口此模块尽量从不同来源获取尽量抓取高匿代理抓取成功之后将可用代理保存到数据库中。 检测模块需要定时检测数据库中的代理。这里需要设置一个检测链接最好是爬取哪个网站就检测哪个网站这样更加有针对性如果要做一个通用型的代理那可以设置百度等链接来检测。另外我们需要标识每一个代理的状态如设置分数标识100 分代表可用分数越少代表越不可用。检测一次如果代理可用我们可以将分数标识立即设置为 100 满分也可以在原基础上加 1 分如果代理不可用可以将分数标识减 1 分当分数减到一定阈值后代理就直接从数据库移除。通过这样的标识分数我们就可以辨别代理的可用情况选用的时候会更有针对性。 接口模块需要用 API 来提供对外服务的接口。其实我们可以直接连接数据库来取对应的数据但是这样就需要知道数据库的连接信息并且要配置连接而比较安全和方便的方式就是提供一个 Web API 接口我们通过访问接口即可拿到可用代理。另外由于可用代理可能有多个那么我们可以设置一个随机返回某个可用代理的接口这样就能保证每个可用代理都可以取到实现负载均衡。
2.2 代理池的实现
文章中的实现在 Github 上创建了项目Python3WebSpider/ProxyPool: An Efficient ProxyPool with Getter, Tester and Server (github.com)
其主要项目在 ProxyPool 中的 proxypool 文件夹中
TodoList