京东作为中国领先的电商平台,其反爬策略复杂且多变,主要体现在以下几个方面:
京东的 API 请求中包含大量动态生成的加密参数(如 eid
、fp
、_t
等),这些参数与用户会话、时间戳和设备信息深度绑定。例如,前端 JavaScript 会生成动态签名(如 sign
参数),同时通过 Canvas、WebGL 等技术采集浏览器指纹,确保请求的合法性和唯一性。
请求时序验证也是京东反爬的重要手段,服务器会检查请求参数的时间有效性,确保请求的时效性。
京东会监测用户的鼠标轨迹、点击模式和页面停留时间,异常行为会触发验证码或直接封禁 IP。例如,如果某个 IP 在短时间内频繁访问页面,或者访问模式不符合正常用户的浏览习惯,京东会认为该行为存在风险。
同一 IP 在短时间内发送过多请求会被暂时封禁。京东对请求频率的限制非常严格,常规的分布式爬虫策略在京东平台上效果有限。
商品详情页采用动态渲染技术,关键数据(如价格、库存)往往通过异步接口加载。这意味着传统的静态 HTML 解析方法无法直接获取这些数据,增加了数据提取的难度。
针对京东的反爬策略,我们可以采取以下应对方法:
设置请求头:通过设置请求头中的 User-Agent
字段,模拟真实的浏览器访问,避免被识别为爬虫。可以使用 fake_useragent
库生成随机的 User-Agent
:Python复制
from fake_useragent import UserAgent
ua = UserAgent()
headers = {'User-Agent': ua.random}
随机延迟:为避免触发频率限制,爬取时可以随机添加延迟。例如:Python复制
import time
import random
time.sleep(random.randint(3, 5))
使用 Selenium 模拟浏览器操作:对于动态加载的内容,可以通过 Selenium 模拟真实用户的浏览器行为,执行 JavaScript 代码,获取动态加载的数据。
京东会限制来自同一 IP 地址的频繁访问,因此使用代理 IP 是绕过反爬虫机制的常用手段。可以通过购买或获取免费代理 IP,随机选择 IP 进行请求。
import requests
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"
proxyMeta = "https://pro.jd.com/mall/active/CeT1FQriLPDZW5mtPdKjYBMEz3L/index.html" % {
"host": proxyHost,
"port": proxyPort,
"user": proxyUser,
"pass": proxyPass,
}
proxies = {
"http": proxyMeta,
"https": proxyMeta,
}
response = requests.get(url, proxies=proxies)
部分网站使用验证码拦截爬虫。应对策略包括手动输入验证码、使用验证码识别服务或尝试通过 API 或其他无需验证码的接口获取数据。例如,可以使用 pytesseract
和 Pillow
库来识别验证码:
from PIL import Image
import pytesseract
captcha_url = 'https://captcha_url'
response = requests.get(captcha_url)
with open('captcha.png', 'wb') as f:
f.write(response.content)
captcha_text = pytesseract.image_to_string(Image.open('captcha.png'))
对于动态生成的加密参数,可以通过分析京东前端代码,定位关键加密函数,并实现相应的算法还原。例如,使用 PyExecJS
或 Node.js
环境执行关键加密函数:Python复制
import time
import hashlib
def generate_jd_signature(product_id):
timestamp = int(time.time() * 1000)
sign_key = hashlib.md5(f"jd_{timestamp}_{product_id}".encode()).hexdigest()
return f"{sign_key[:8]}-{sign_key[8:12]}-{sign_key[12:16]}-{sign_key[16:20]}-{sign_key[20:]}"
User-Agent
、Accept-Language
等。BeautifulSoup
或 lxml
结合正则表达式进行解析。以下是一个完整的 Python 爬虫代码示例,用于爬取京东商品详情:
import requests
from fake_useragent import UserAgent
import time
import random
from bs4 import BeautifulSoup
# 设置请求头
ua = UserAgent()
headers = {'User-Agent': ua.random}
# 使用代理 IP
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"
proxyMeta = "https://pro.jd.com/mall/active/CeT1FQriLPDZW5mtPdKjYBMEz3L/index.html" % {
"host": proxyHost,
"port": proxyPort,
"user": proxyUser,
"pass": proxyPass,
}
proxies = {
"http": proxyMeta,
"https": proxyMeta,
}
# 动态生成签名
def generate_jd_signature(product_id):
timestamp = int(time.time() * 1000)
sign_key = hashlib.md5(f"jd_{timestamp}_{product_id}".encode()).hexdigest()
return f"{sign_key[:8]}-{sign_key[8:12]}-{sign_key[12:16]}-{sign_key[16:20]}-{sign_key[20:]}"
# 爬取商品详情
def get_product_details(product_id):
url = f"https://item.jd.com/{product_id}.html"
signature = generate_jd_signature(product_id)
params = {
"sign": signature,
"timestamp": int(time.time() * 1000)
}
response = requests.get(url, headers=headers, params=params, proxies=proxies)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# 提取商品信息
product_name = soup.find('div', class_='sku-name').text.strip()
product_price = soup.find('span', class_='price').text.strip()
print(f"商品名称:{product_name}")
print(f"商品价格:{product_price}")
else:
print(f"请求失败,状态码:{response.status_code}")
# 主函数
if __name__ == "__main__":
product_id = "123456" # 替换为实际商品 ID
get_product_details(product_id)
在爬取京东数据时,务必遵循以下合规性注意事项:
robots.txt
协议:京东明确禁止部分路径的爬取。京东的反爬机制平均每 2-3 周会有小的更新,每季度会有大的调整。建议采取以下维护措施:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。