在Python3爬虫中,使用代理是一種防止IP被禁或者提高爬取速度的常用方法,主要用於模拟多個IP地址進行訪問。代理可以分為免费代理和付费代理兩種,其中免费代理不穩定,而付费代理相對比較穩定可靠。
以下是 Python3 爬虫代理的使用场景和應用:
防止 IP 被封鎖:有些網站會設置 IP 訪問頻率限制,如果訪問次数超過限制,則該 IP 將被禁止訪問網站,使用代理能夠避免這種情況發生。
提高爬取速度:使用代理可以同時建立多個连接,從而實現快速爬取目标數據的目的。
绕過地域限制:某些網站在不同的区域提供的服務不同,如果你需要訪問某些只针對特定地区開放的網站,使用代理可以绕過這種限制,使你可以得到所需的數據。
總之,代理IP在 Python3 爬虫中扮演着非常重要的角色。由於使用代理也會带來一些安全問题,因此在使用代理時,需要注意選择合適的代理服務商,並嚴格遵守網絡安全规定。
准备工作
我們需要先获取一個可用代理,代理就是 IP 地址和端口的組合,就是 ip:端口 這樣的格式。如果代理需要訪問認證,那就還需要额外的用戶名密碼兩個資訊。
這裡我的本機安裝了一部代理軟件,它會在本地 7890 端口上创建 HTTP 代理服務,即代理為 127.0.0.1:7890。另外,該軟件還會在 7891 端口上创建 SOCKS 代理服務,即代理為 127.0.0.1:7891,所以只要設置了這個代理,就可以成功將本機 IP 切换到代理軟件连接的服務器的 IP 了。
在本章下面的示例裡,我使用上述代理來演示其設置方法,你也可以自行替换成自己的可用代理。
設置代理後,測試的網址是 http://httpbin.org/get 訪問該鏈接我們可以得到請求的相關資訊,其中返回結果的 origin 字段就是客戶端的 IP,我們可以根据它來判断代理是否設置成功,即是否成功伪装了 IP。
好,接下來我們就來看下各個請求库的代理設置方法吧。
获取Python3爬虫代理
一些網站會檢測對其數據的频繁訪問,並采取措施阻止這些訪問。使用代理服務器可以分散訪問來源,减少被檢測的可能性,從而增加爬取成功率。
最佳美國静态代理IP
IPRoyal是一家對中國地区极其友好的代理服務提供商其住宅代理解決方案极具吸引力
查看IPRoyal
最實惠的静态代理
Shifter.io是一家知名的代理服務提供商,旨在為用戶提供隱私保護和更好的互聯網体验。
查看Shifter.io
2. urllib
首先我們以最基础的 urllib 為例,來看一下代理的設置方法,代碼如下:
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy = '127.0.0.1:7890'
proxy_handler = ProxyHandler({
'http': 'http://' + proxy,
'https': 'http://' + proxy
})
opener = build_opener(proxy_handler)
try:
response = opener.open('https://httpbin.org/get')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
運行結果如下:
{
"args": {},
"headers": {
"Accept-Encoding": "identity",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.7",
"X-Amzn-Trace-Id": "Root=1-60e9a1b6-0a20b8a678844a0b2ab4e889"
},
"origin": "210.173.1.204",
"url": "https://httpbin.org/get"
}
這裡我們需要借助 ProxyHandler 設置代理,參數是字典類型,键名為协议類型,键值是代理。注意,此處代理前面需要加上协议,即 http:// 或者 https://,当請求的鏈接是 HTTP 协议的時候,會使用 http 键名對應的代理,当請求的鏈接是 HTTPS 协议的時候,會使用 https 键名對應的代理。不過這裡我們把代理本身設置為了 HTTP 协议,即前缀統一設置為了
http://,所以不論訪問 HTTP 還是 HTTPS 协议的鏈接,都會使用我們配置的 HTTP 协议的代理進行請求。
创建完 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_opener
proxy = 'username:password@127.0.0.1:7890'
proxy_handler = ProxyHandler({
'http': 'http://' + proxy,
'https': 'http://' + proxy
})
opener = build_opener(proxy_handler)
try:
response = opener.open('https://httpbin.org/get')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
這裡改變的只是 proxy 變量,只需要在代理前面加入代理認證的用戶名密碼即可,其中 username 就是用戶名,password 為密碼,例如 username 為 foo,密碼為 bar,那麼代理就是 foo:bar@127.0.0.1:7890。
如果代理是 SOCKS5 類型,那麼可以用如下方式設置代理:
import socks
import socket
from urllib import request
from urllib.error import URLError
socks.set_default_proxy(socks.SOCKS5, '127.0.0.1', 7891)
socket.socket = socks.socksocket
try:
response = request.urlopen('https://httpbin.org/get')
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
此處需要一個 socks 模块,可以通過如下命令安裝:
pip3 install PySocks
這裡需要本地運行一個 SOCKS5 代理,運行在 7891 端口,運行成功之後和上文 HTTP 代理输出結果是一樣的:
{
"args": {},
"headers": {
"Accept-Encoding": "identity",
"Host": "httpbin.org",
"User-Agent": "Python-urllib/3.7",
"X-Amzn-Trace-Id": "Root=1-60e9a1b6-0a20b8a678844a0b2ab4e889"
},
"origin": "210.173.1.204",
"url": "https://httpbin.org/get"
}
結果的 origin 字段同樣為代理的 IP,代理設置成功。
3.requests 的代理設置
對於 requests 來說,代理設置非常简單,我們只需要传入 proxies 參數即可。
這裡以我本機的代理為例,來看下 requests 的 HTTP 代理設置,代碼如下:
import requests
proxy = '127.0.0.1:7890'
proxies = {
'http': 'http://' + proxy,
'https': 'http://' + proxy,
}
try:
response = requests.get('https://httpbin.org/get', proxies=proxies)
print(response.text)
except requests.exceptions.ConnectionError as e:
print('Error', e.args)
運行結果如下:
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0",
"X-Amzn-Trace-Id": "Root=1-5e8f358d-87913f68a192fb9f87aa0323"
},
"origin": "210.173.1.204",
"url": "https://httpbin.org/get"
}
和 urllib 一樣,当請求的鏈接是 HTTP 协议的時候,會使用 http 键名對應的代理,当請求的鏈接是 HTTPS 协议的時候,會使用 https 键名對應的代理,不過這裡統一使用了 HTTP 协议的代理。
運行結果中的 origin 若是代理服務器的 IP,則證明代理已經設置成功。
如果代理需要認證,那麼在代理的前面加上用戶名和密碼即可,代理的写法就變成如下所示:
proxy = 'username:password@127.0.0.1:7890'
這裡只需要將 username 和 password 替换即可。
如果需要使用 SOCKS 代理,則可以使用如下方式來設置:
import requests
proxy = '127.0.0.1:7891'
proxies = {
'http': 'socks5://' + proxy,
'https': 'socks5://' + proxy
}
try:
response = requests.get('https://httpbin.org/get', proxies=proxies)
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",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0",
"X-Amzn-Trace-Id": "Root=1-5e8f364a-589d3cf2500fafd47b5560f2"
},
"origin": "210.173.1.204",
"url": "https://httpbin.org/get"
}
另外,還有一種設置方式,即使用 socks 模块,也需要像上文一樣安裝 socks 库。這種設置方法如下所示:
import requests
import socks
import socket
socks.set_default_proxy(socks.SOCKS5, '127.0.0.1', 7891)
socket.socket = socks.socksocket
try:
response = requests.get('https://httpbin.org/get')
print(response.text)
except requests.exceptions.ConnectionError as e:
print('Error', e.args)
使用這種方法也可以設置 SOCKS 代理,運行結果完全相同。相比第一種方法,此方法是全局設置的。我們可以在不同情況下選用不同的方法。
4. httpx 的代理設置
httpx 的用法本身就與 requests 的使用非常相似,所以其也是通過 proxies 參數來設置代理的,不過與 requests 不同的是,proxies 參數的键名不能再是 http 或 https,而需要更改為 http:// 或 https://,其他的設置是一樣的。
對於 HTTP 代理來說,設置方法如下:
import httpx
proxy = '127.0.0.1:7890'
proxies = {
'http://': 'http://' + proxy,
'https://': 'http://' + proxy,
}
with httpx.Client(proxies=proxies) as client:
response = client.get('https://httpbin.org/get')
print(response.text)
對於需要認證的代理,也是改下 proxy 的值即可:
proxy = 'username:password@127.0.0.1:7890'
這裡只需要將 username 和 password 替换即可。
運行結果和使用 requests 是類似的,結果如下:
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-httpx/0.18.1",
"X-Amzn-Trace-Id": "Root=1-60e9a3ef-5527ff6320484f8e46d39834"
},
"origin": "210.173.1.204",
"url": "https://httpbin.org/get"
}
對於 SOCKS 代理,我們需要安裝 httpx-socks 库,安裝方法如下:
pip3 install "httpx-socks[asyncio]"
這樣會同時安裝同步和异步兩種模式的支持。
對於同步模式,設置方法如下:
import httpx
from httpx_socks import SyncProxyTransport
transport = SyncProxyTransport.from_url(
'socks5://127.0.0.1:7891')
with httpx.Client(transport=transport) as client:
response = client.get('https://httpbin.org/get')
print(response.text)
這裡我們需要設置一個 transport 對象,並配置 SOCKS 代理的地址,同時在声明 httpx 的 Client 對象的時候传入 transport 參數即可,運行結果和刚才是一樣的。
對於异步模式,設置方法如下:
import httpx
import asyncio
from httpx_socks import AsyncProxyTransport
transport = AsyncProxyTransport.from_url(
'socks5://127.0.0.1:7891')
async def main():
async with httpx.AsyncClient(transport=transport) as client:
response = await client.get('https://httpbin.org/get')
print(response.text)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
和同步模式不同的是,transport 對象我們用的是 AsyncProxyTransport 而不是 SyncProxyTransport,同時需要將 Client 對象更改為 AsyncClient 對象,其他的不變,運行結果是一樣的。
5. Selenium 的代理設置
Selenium 同樣可以設置代理,這裡以 Chrome 為例來介紹其設置方法。
對於無認證的代理,設置方法如下:
from selenium import webdriver
proxy = '127.0.0.1:7890'
options = webdriver.ChromeOptions()
options.add_argument('--proxy-server=http://' + proxy)
browser = webdriver.Chrome(options=options)
browser.get('https://httpbin.org/get')
print(browser.page_source)
browser.close()
運行結果如下:
{
"args": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-5e8f39cd-60930018205fd154a9af39cc"
},
"origin": "210.173.1.204",
"url": "http://httpbin.org/get"
}
代理設置成功,origin 同樣為代理 IP 的地址。
如果代理是認證代理,則設置方法相對比較繁琐,具体如下所示:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import zipfile
ip = '127.0.0.1'
port = 7890
username = 'foo'
password = 'bar'
manifest_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)
options = Options()
options.add_argument("--start-maximized")
options.add_extension(plugin_file)
browser = webdriver.Chrome(options=options)
browser.get('https://httpbin.org/get')
print(browser.page_source)
browser.close()
這裡需要在本地创建一個 manifest.json 配置文件和 background.js 脚本來設置認證代理。運行代碼之後,本地會生成一個 proxy_auth_plugin.zip 文件來保存当前配置。
運行結果和上例一致,origin 同樣為代理 IP。
SOCKS 代理的設置也比較简單,把對應的协议修改為 socks5 即可,如無密碼認證的代理設置方法為:
from selenium import webdriver
proxy = '127.0.0.1:7891'
options = webdriver.ChromeOptions()
options.add_argument('--proxy-server=socks5://' + proxy)
browser = webdriver.Chrome(options=options)
browser.get('https://httpbin.org/get')
print(browser.page_source)
browser.close()
運行結果是一樣的。
6.aiohttp 的代理設置
對於 aiohttp 來說,我們可以通過 proxy 參數直接設置。HTTP 代理設置如下:
import asyncio
import aiohttp
proxy = 'http://127.0.0.1:7890'
async def main():
async with aiohttp.ClientSession() as session:
async with session.get('https://httpbin.org/get', proxy=proxy) as response:
print(await response.text())
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
如果代理有用戶名和密碼,像 requests 一樣,把 proxy 修改為如下內容:
proxy = 'http://username:password@127.0.0.1:7890'
這裡只需要將 username 和 password 替换即可。
對於 SOCKS 代理,我們需要安裝一個支持库 aiohttp-socks,其安裝命令如下:
pip3 install aiohttp-socks
我們可以借助於這個库的 ProxyConnector 來設置 SOCKS 代理,其代碼如下:
import asyncio
import aiohttp
from aiohttp_socks import ProxyConnector
connector = ProxyConnector.from_url('socks5://127.0.0.1:7891')
async def main():
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get('https://httpbin.org/get') as response:
print(await response.text())
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
運行結果是一樣的。
另外,這個库還支持設置 SOCKS4、HTTP 代理以及對應的代理認證,可以参考其官方介紹。
7. Pyppeteer 的代理設置
對於 Pyppeteer 來說,由於其默认使用的是類似 Chrome 的 Chromium 瀏覽器,因此其設置方法和 Selenium 的 Chrome 一樣,如 HTTP 無認證代理設置方法都是通過 args 來設置的,實現如下:
import asyncio
from pyppeteer import launch
proxy = '127.0.0.1:7890'
async def main():
browser = await launch({'args': ['--proxy-server=http://' + proxy], 'headless': False})
page = await browser.newPage()
await page.goto('https://httpbin.org/get')
print(await page.content())
await browser.close()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
運行結果如下:
{
"args": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3494.0 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-5e8f442c-12b1ed7865b049007267a66c"
},
"origin": "210.173.1.204",
"url": "https://httpbin.org/get"
}
同樣可以看到設置成功。
SOCKS 代理也一樣,只需要將协议修改為 socks5 即可,代碼實現如下:
import asyncio
from pyppeteer import launch
proxy = '127.0.0.1:7891'
async def main():
browser = await launch({'args': ['--proxy-server=socks5://' + proxy], 'headless': False})
page = await browser.newPage()
await page.goto('https://httpbin.org/get')
print(await page.content())
await browser.close()
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
運行結果也是一樣的。
8. Playwright 的代理設置
相對 Selenium 和 Pyppeteer 來說,Playwright 的代理設置更加方便,其预留了一個 proxy 參數,可以在啟動 Playwright 的時候設置。
對於 HTTP 代理來說,可以這樣設置:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(proxy={
'server': 'http://127.0.0.1:7890'
})
page = browser.new_page()
page.goto('https://httpbin.org/get')
print(page.content())
browser.close()
在调用 launch 方法的時候,我們可以传一個 proxy 參數,是一個字典。字典有一個必填的字段叫做 server,這裡我們可以直接填写 HTTP 代理的地址即可。
運行結果如下:
{
"args": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Host": "httpbin.org",
"Sec-Ch-Ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"92\"",
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4498.0 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-60e99eef-4fa746a01a38abd469ecb467"
},
"origin": "210.173.1.204",
"url": "https://httpbin.org/get"
}
對於 SOCKS 代理,設置方法也是完全一樣的,我們只需要把 server 字段的值换成 SOCKS 代理的地址即可:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(proxy={
'server': 'socks5://127.0.0.1:7891'
})
page = browser.new_page()
page.goto('https://httpbin.org/get')
print(page.content())
browser.close()
運行結果和刚才也是完全一樣的。
對於有用戶名和密碼的代理,Playwright 的設置也非常简單,我們只需要在 proxy 參數额外設置 username 和 password 字段即可,假如用戶名和密碼分别是 foo 和 bar,則設置方法如下:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(proxy={
'server': 'http://127.0.0.1:7890',
'username': 'foo',
'password': 'bar'
})
page = browser.new_page()
page.goto('https://httpbin.org/get')
print(page.content())
browser.close()
這樣我們就能非常方便地為 Playwright 實現認證代理的設置。
9. 總结
以上我們就總结了各個請求库的代理使用方式,各種库的設置方法大同小异,学會了這些方法之後,以後如果遇到封 IP 的問题,我們可以輕松通過加代理的方式來解決。
通過使用位於不同地理位置的代理服務器,可以模拟在不同的地理位置上進行爬取,並获取特定区域的數據。這對於需要获取地理相關數據的任務非常有用。通過使用代理服務器,可以隱藏爬虫的真實 IP 地址,從而避免被網站禁止訪問或限制頻率。這也有助於保護你的隱私和安全。一些網站通過识别並阻止來自同一IP地址的過多請求來防止爬虫。使用代理服務器可以绕過此類反爬機制,允許你以更快的速度和更高的成功率爬取數據。