Django部署Linux服务器后爬虫被拦截,获BufferedReader响应求助
先直接针对你的问题拆解分析,本地正常但服务器部署后被拦截,核心是目标网站的反爬机制识别了服务器环境的特征,而非单纯的请求头问题。下面一步步给你解决方案:
一、先处理你用urllib.request.FancyURLopener得到的响应
那个<addinfourl>是urllib的原生响应实例,你可以这样读取内容并解析:
def scrape(): opener = AppURLopener() response = opener.open(url) # 读取响应的HTML内容 html_content = response.read() # 传给BeautifulSoup解析 soup = BeautifulSoup(html_content, 'html.parser') print(soup)
不过这个方法本质和改User-Agent的思路一致,大概率还是会被拦截,我们接着看更有效的方案。
二、为什么Linux服务器会被拦截而本地不会?
目标网站的反爬可能检测了这些点:
- IP特征:云服务器IP段常被标记为爬虫聚集地,可能已进入对方黑名单;或者你请求频率过高触发了阈值。
- 请求环境差异:Linux服务器的请求缺少真实浏览器的完整请求头(比如
Sec-Fetch-*系列、Cookie),或者网站通过TLS/SSL指纹识别出非浏览器请求。 - 会话特征:本地浏览器有缓存的Cookie、会话信息,而服务器是全新请求,容易被识别。
三、先别急着换Selenium,试试这些低成本优化
1. 复制真实浏览器的完整请求头
你现有的请求头不够全面,直接复制Chrome访问目标网站时的全部Request Headers(包括Cookie、Sec-Fetch系列头),示例:
hdr = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', '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-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'none', 'Sec-Fetch-User': '?1', # 把你本地浏览器访问时的Cookie复制过来 'Cookie': 'xxx=xxx; yyy=yyy' } req = get(url, headers=hdr)
注意:Accept-Encoding别设为none,真实浏览器都支持压缩,设成gzip, deflate, br更贴合真实请求。
2. 添加随机请求延迟
服务器环境下请求频率太规律,很容易被检测。每次请求后加随机延迟模拟人类操作:
import time import random # 每次请求后随机延迟1-3秒,可根据需求调整范围 time.sleep(random.uniform(1, 3))
3. 更换代理IP
如果服务器IP已被拉黑,试试用代理IP。requests配置代理的方式:
proxies = { 'http': 'http://your-proxy-ip:port', 'https': 'https://your-proxy-ip:port' } req = get(url, headers=hdr, proxies=proxies)
可以先试试免费代理池(注意稳定性),效果不好再考虑付费代理服务。
4. 缓存请求避免重复访问
用requests-cache缓存已请求过的页面,减少重复请求次数:
from requests_cache import CachedSession # 缓存1小时内的请求 session = CachedSession('scraper_cache', expire_after=3600) req = session.get(url, headers=hdr)
四、什么时候考虑换Selenium?
如果上面的方法都无效,再用Selenium——它模拟真实浏览器的渲染行为,反爬难度更高。但Linux服务器上需要配置无头浏览器:
from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() options.add_argument('--headless=new') # 无头模式 options.add_argument('--no-sandbox') # 解决Linux环境权限问题 options.add_argument('--disable-dev-shm-usage') # 避免内存不足 options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36') driver = webdriver.Chrome(options=options) driver.get(url) html_content = driver.page_source soup = BeautifulSoup(html_content, 'html.parser') print(soup) driver.quit()
注意:Linux服务器需要安装Chrome浏览器和对应版本的ChromeDriver,还要安装依赖库(比如libnss3、libgconf-2-4)。
五、关于更换部署方式(比如Heroku)
换Heroku不一定能解决问题——Heroku的IP段同样可能被目标网站标记。除非你能确定当前服务器IP已被拉黑,否则优先优化爬虫本身的反爬适配,而非换平台。如果要换,可试试带动态IP的云服务,或者自己搭建代理池。
最后提醒:爬虫要遵守目标网站的robots.txt协议,不要过度请求,避免给对方服务器造成压力,否则可能面临法律风险哦。
内容的提问来源于stack exchange,提问作者Ahmed Mujtaba

