【ScrapeCenter】爬虫案例实战教程
ScrapeCenter爬虫练习
内容案例来自:https://scrape.center/
本人小白菜,仅供参考哦~
文章目录
ssr1 & ssr2
案例ssr1:电影数据网站,无反爬,数据通过服务端渲染,适合基本爬虫练习。
案例ssr2:电影数据网站,无反爬,无 HTTPS 证书,适合用作 HTTPS 证书验证。
分析:这里使用request库,直接参考代码即可
import requests
from lxml import etree
'''
ScrapeCenter ssr1 & ssr2
'''
# 数组url
urls = ["https://ssr1.scrape.center/page/{}".format(i) for i in range(1,11)]
# 用于去除返回的数组中的空格
def getText(list):
try:
return list[0].strip()
except:
return ""
for url in urls:
# 请求目标地址
response = requests.get(url)
print(response.status_code)
# 解析数据
html = etree.HTML(response.text)
# 定位data列表
data_list = html.xpath('//*[@id="index"]/div[1]/div[1]/div')
print(len(data_list))
for data in data_list:
print(data.text)
img_src = getText(data.xpath('./div/div/div[1]/a/img/@src'))
title = getText(data.xpath('./div/div/div[2]/a/h2/text()'))
types = data.xpath('./div/div/div[2]/div[1]/button/span/text()')
position = getText(data.xpath('./div/div/div[2]/div[2]/span[1]/text()'))
total = getText(data.xpath('./div/div/div[2]/div[2]/span[3]/text()'))
release = getText(data.xpath('./div/div/div[2]/div[3]/span/text()'))
score = getText(data.xpath('./div/div/div[3]/p[1]/text()'.strip()))
print(img_src, title, types, position, total, release, score)
srr3
案例ssr3:电影数据网站,无反爬,带有 HTTP BasicAuthentication,适合用作 HTTP 认证案例,用户名密码均为 admin。
带有 HTTPBasic Authentication,Python的requests库中,可以使用auth参数来指定Basic Auth的凭据。requests.auth.HTTPBasicAuth类允许你传递用户名和密码。
import requests
from lxml import etree
from requests.auth import HTTPBasicAuth
'''
ScrapeCenter ssr3
'''
# 数组url
urls = ["https://ssr3.scrape.center/page/{}".format(i) for i in range(1,11)]
# 用户名和密码
username = 'admin'
password = 'admin'
# 用于去除返回的数组中的空格
def getText(list):
try:
return list[0].strip()
except:
return ""
for url in urls:
# 请求目标地址
response = requests.get(url,auth=HTTPBasicAuth(username,password))
print(response.status_code)
# 解析数据
html = etree.HTML(response.text)
# 定位data列表
data_list = html.xpath('//*[@id="index"]/div[1]/div[1]/div')
print(len(data_list))
for data in data_list:
print(data.text)
img_src = getText(data.xpath('./div/div/div[1]/a/img/@src'))
title = getText(data.xpath('./div/div/div[2]/a/h2/text()'))
types = data.xpath('./div/div/div[2]/div[1]/button/span/text()')
position = getText(data.xpath('./div/div/div[2]/div[2]/span[1]/text()'))
total = getText(data.xpath('./div/div/div[2]/div[2]/span[3]/text()'))
release = getText(data.xpath('./div/div/div[2]/div[3]/span/text()'))
score = getText(data.xpath('./div/div/div[3]/p[1]/text()'.strip()))
print(img_src, title, types, position, total, release, score)
ssr4
案例ssr4:电影数据网站,无反爬,每个响应增加了5秒延迟,适合测试慢速网站爬取或做爬取速度测试,减少网速干扰。
分析:每个响应增加5s延迟,直接time.sleep(5)即可
import time
import requests
from anyio import sleep
from lxml import etree
'''
ScrapeCenter ssr4
'''
# 数组url
urls = ["https://ssr4.scrape.center/page/{}".format(i) for i in range(1,11)]
# 用于去除返回的数组中的空格
def getText(list):
try:
return list[0].strip()
except:
return ""
for url in urls:
# 请求目标地址
response = requests.get(url)
time.sleep(5)
print(response.status_code)
# 解析数据
html = etree.HTML(response.text)
# 定位data列表
data_list = html.xpath('//*[@id="index"]/div[1]/div[1]/div')
print(len(data_list))
for data in data_list:
print(data.text)
img_src = getText(data.xpath('./div/div/div[1]/a/img/@src'))
title = getText(data.xpath('./div/div/div[2]/a/h2/text()'))
types = data.xpath('./div/div/div[2]/div[1]/button/span/text()')
position = getText(data.xpath('./div/div/div[2]/div[2]/span[1]/text()'))
total = getText(data.xpath('./div/div/div[2]/div[2]/span[3]/text()'))
release = getText(data.xpath('./div/div/div[2]/div[3]/span/text()'))
score = getText(data.xpath('./div/div/div[3]/p[1]/text()'.strip()))
print(img_src, title, types, position, total, release, score)
spa1
案例spa1:电影数据网站,无反爬,数据通过 Ajax 加载,页面动态渲染,适合 Ajax 分析和动态页面渲染爬取。
分析:需要使用selenium自动化,设置等待时间或者使用显式等待,等待页面数据渲染完毕。
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
'''
ScrapeCenter spa1
'''
# 数组url
urls = ["https://spa1.scrape.center/page/{}".format(i) for i in range(1,11)]
# 浏览器对象
driver = webdriver.Chrome()
for url in urls:
driver.get(url)
# 等待Ajax渲染完成(可配合显式等待优化)
wait = WebDriverWait(driver, 10)
# 设置判断条件:等待XPATH的元素加载完成
wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="index"]/div[1]/div[1]/div')))
data_list = driver.find_elements(By.XPATH,'//*[@id="index"]/div[1]/div[1]/div')
for data in data_list:
print(data.text)
driver.quit()
spa2
案例spa2:电影数据网站,无反爬,数据通过 Ajax 加载,数据接口参数加密且有时间限制,适合动态页面渲染爬取或 JavaScript 逆向分析。
分析:js逆向,打断点分析。
import execjs
import requests
'''
ScrapeCenter spa2
'''
with open('./spa2.js', 'r', encoding='utf-8') as f:
js_code = f.read()
for j in range(0,110,10):
token = execjs.compile(js_code).call("i",str(j))
url = f"https://spa2.scrape.center/api/movie/?limit=10&offset={j}&token={token}"
response = requests.get(url)
print(response.status_code)
print(response.text)
spa3
案例spa3:电影数据网站,无反爬,数据通过 Ajax 加载,无页码翻页,下拉至底部刷新,适合Ajax 分析和动态页面渲染爬取。
分析:Ajax进行数据加载,不使用翻页,通过下拉页面至底部进行刷新
up这里考虑了很久,尝试使用DrissionPage,但是也无法达到满意的效果
由于发现这个页面存在浏览器滚动条和DIV内嵌滚动条,这里需要对内嵌的DIV滚动条进行滚动,如果使用window.scrollxx进行滚动,都是滚动浏览器滚动条,无法实现加载新数据。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
'''
ScrapeCenter spa3
'''
# 设置浏览器对象选项,确保开启javaScript
chrome_options = Options()
chrome_options.add_argument("--enable-javascript")
driver = webdriver.Chrome()
driver.get("https://spa3.scrape.center/")
# 这里的次数尝试一下,看滚动几次能够获取到所有的请求,这样所有的电影数据就全加载到页面了
for i in range(1, 4):
print(f"第{i}次执行js")
# js语句,可以先在页面控制台尝试如何进行滚动
js = 'document.getElementById("index").scrollTop=document.getElementById("index").scrollHeight'
result = driver.execute_script(js)
time.sleep(2)
data_list = driver.find_elements(By.XPATH, '//*[@id="index"]/div/div/div')
print(len(data_list))
for data in data_list:
print(data.text)
driver.quit()
spa4
案例spa4:新闻网站索引,无反爬,数据通过 Ajax 加载,无页码翻页,适合 Ajax 分析和动态页面渲染抓取以及智能页面提取分析。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
'''
ScrapeCenter spa4
'''
# 需要判断一下元素加载是否完成,不然太快无法爬取到数据
# 设置浏览器对象选项,确保开启javaScript
chrome_options = Options()
chrome_options.add_argument("--enable-javascript")
driver = webdriver.Chrome()
driver.get("https://spa4.scrape.center/")
# 等待Ajax渲染完成(可配合显式等待优化)
wait = WebDriverWait(driver, 10)
# 设置判断条件:等待XPATH的元素加载完成
wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="index"]/div/div/div')))
data_list = driver.find_elements(By.XPATH,'//*[@id="index"]/div/div/div')
print(len(data_list))
for data in data_list:
print(data.text)
driver.quit()
spa5
案例spa5:图书网站,无反爬,数据通过 Ajax 加载,有翻页,适合大批量动态页面渲染抓取。
分析:卡住了,本来打算使用selenium等待数据渲染到页面,逐页爬取,发现爬不到,已经使用:WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, ‘//*[@id=“index”]/div[1]/div/div/div’))),但无法解决,随后通过使用time.slepp(1) 强制等待,又发现有的页中容易出现爬不到、爬不完整的情况,增加等待时间为2s,也容易存在爬不到的问题,并且还慢…。(已贴代码,有大佬可以帮忙分析一下原因,感谢~)
于是想到可以直接通过API获取,刚好这里没有对接口进行加密或鉴权。
import requests
'''
ScrapeCenter spa5
'''
urls = ["https://spa5.scrape.center/api/book/?limit=18&offset={}".format(i) for i in range(0,9037,18)]
i = 0
for url in urls:
i += 1
print(f"正在爬取第{i}页图书:")
response = requests.get(url)
data = response.json() # 直接解析 JSON
for data in data["results"]:
list_author = data["authors"]
# 使用列表推导式去除空格和换行
authors = [x.replace('\n','').replace(' ','') for x in list_author]
print(f"id:{data['id']},电影名:{data['name']},作者:{authors}")
# 以下为selenium
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
'''
ScrapeCenter spa5
'''
urls = ["https://spa5.scrape.center/page/{}".format(i) for i in range(1,504)]
driver = webdriver.Chrome()
for url in urls:
driver.get(url)
# 强制等待2s 不容易出现爬取不到的情况
time.sleep(2)
# 等待Ajax渲染完成(可配合显式等待优化)
try:
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, '//*[@id="index"]/div[1]/div/div/div'))
)
except:
print("超时,未找到列表")
data_list = driver.find_elements(By.XPATH,'//*[@id="index"]/div[1]/div/div/div')
print(len(data_list))
for data in data_list:
print(data.text)
driver.quit()
spa6
案例spa6:电影数据网站,数据通过 Ajax 加载,数据接口参数加密且有时间限制,源码经过混淆,适合 JavaScript 逆向分析。
import base64
import execjs
import requests
'''
ScrapeCenter spa6
'''
with open('./spa6.js','r',encoding='utf-8') as f:
file=f.read()
take=execjs.compile(file).call("_0x456254")
url_id=base64.b64encode(take.encode('utf-8'))
token=url_id.decode()
print(token)
urls = ["https://spa6.scrape.center/api/movie?limit=10&offset={}&token={}".format(i,token) for i in range(0,100,10)]
for url in urls:
print(url)
response = requests.get(url)
print(response.status_code)
data = response.json()
for data in data['results']:
print(data)
spa7 & spa8
案例spa7:NBA 球星数据网站,数据纯前端渲染Token 经过加密处理,适合基础 JavaScript模拟分析。
案例spa8:NBA 球星数据网站,数据纯前端渲染,Token 经过加密处理,JavaScript 代码一行混入 HTML代码,防止直接调试,适合JavaScript 逆向分析。
1、定义python方法进行加密解密
import base64
from Crypto.Cipher import DES
from Crypto.Util.Padding import pad
'''
ScrapeCenter spa7 & spa8 & spa9 & spa10
'''
# 原始球员数据(JSON格式)
players =[
{
'name': '凯文-杜兰特',
'image': 'durant.png',
'birthday': '1988-09-29',
'height': '208cm',
'weight': '108.9KG'
}, {
'name': '勒布朗-詹姆斯',
'image': 'james.png',
'birthday': '1984-12-30',
'height': '206cm',
'weight': '113.4KG'
}, {
'name': '斯蒂芬-库里',
'image': 'curry.png',
'birthday': '1988-03-14',
'height': '191cm',
'weight': '83.9KG'
}, {
'name': '詹姆斯-哈登',
'image': 'harden.png',
'birthday': '1989-08-26',
'height': '196cm',
'weight': '99.8KG'
}, {
'name': '扬尼斯-安特托昆博',
'image': 'antetokounmpo.png',
'birthday': '1994-12-06',
'height': '211cm',
'weight': '109.8KG'
}, {
'name': '拉塞尔-威斯布鲁克',
'image': 'westbrook.png',
'birthday': '1988-11-12',
'height': '191cm',
'weight': '90.7KG'
}, {
'name': '凯里-欧文',
'image': 'irving.png',
'birthday': '1992-03-23',
'height': '188cm',
'weight': '88.5KG'
}, {
'name': '安东尼-戴维斯',
'image': 'davis.png',
'birthday': '1993-03-11',
'height': '208cm',
'weight': '114.8KG'
}, {
'name': '乔尔-恩比德',
'image': 'embiid.png',
'birthday': '1994-03-16',
'height': '213cm',
'weight': '127.0KG'
}, {
'name': '克雷-汤普森',
'image': 'thompson.png',
'birthday': '1990-02-08',
'height': '198cm',
'weight': '97.5KG'
}, {
'name': '考瓦伊-莱昂纳德',
'image': 'leonard.png',
'birthday': '1991-06-29',
'height': '201cm',
'weight': '102.1KG'
}, {
'name': '达米安-利拉德',
'image': 'lillard.png',
'birthday': '1990-07-15',
'height': '188cm',
'weight': '88.5KG'
}, {
'name': '卡梅罗-安东尼',
'image': 'anthony.png',
'birthday': '1984-05-29',
'height': '203cm',
'weight': '108KG'
}, {
'name': '尼科拉-约基奇',
'image': 'jokic.png',
'birthday': '1995-02-19',
'height': '213cm',
'weight': '128.8KG'
}, {
'name': '卡尔-安东尼-唐斯',
'image': 'towns.png',
'birthday': '1995-11-15',
'height': '211cm',
'weight': '112.5KG'
}, {
'name': '克里斯-保罗',
'image': 'paul.png',
'birthday': '1985-05-06',
'height': '185cm',
'weight': '79.4KG'
},
]
# 密钥(截取前8字节)
SECRET_KEY = 'fipFfVsZsTda94hJNKJfLoaqyqMZFFimwLt'[:8].encode('utf-8')
def get_token(player):
"""生成球员的DES加密令牌"""
# 将name转为Base64
base64_name = base64.b64encode(player['name'].encode('utf-8')).decode('utf-8')
# 拼接明文
plaintext = f"{base64_name}{player['birthday']}{player['height']}{player['weight']}"
plain_bytes = plaintext.encode('utf-8')
# DES加密(ECB模式 + PKCS7填充)
cipher = DES.new(SECRET_KEY, DES.MODE_ECB)
padded_bytes = pad(plain_bytes, 8) # PKCS7填充到8字节倍数
encrypted = cipher.encrypt(padded_bytes)
# 返回Base64编码结果
return base64.b64encode(encrypted).decode('utf-8')
# 示例使用
if __name__ == "__main__":
# 为每个球员生成token
for player in players:
token = get_token(player)
print(f"{player['name']} 的Token: {token}")
2、调用js文件
import execjs
'''
ScrapeCenter spa7 & spa8 & spa9 & spa10 & spa11 & spa12
'''
# 测试数据
player = {
'name': '勒布朗-詹姆斯',
'image': 'james.png',
'birthday': '1984-12-30',
'height': '206cm',
'weight': '113.4KG'
}
with open('js/spa7.js', 'r', encoding='utf-8') as f:
file=f.read()
take=execjs.compile(file).call("getToken",player)
print(take)
const CryptoJS = require("crypto-js")
function getToken(player) {
let key = CryptoJS.enc.Utf8.parse("fipFfVsZsTda94hJNKJfLoaqyqMZFFimwLt");
const {name, birthday, height, weight} = player;
let base64Name = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(name));
let encrypted = CryptoJS.DES.encrypt(`${base64Name}${birthday}${height}${weight}`, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
spa9
案例spa9:NBA 球星数据网站,数据纯前端渲染,Token 经过加密处理,JavaScript 经过 eval混淆,适台 JavaScript 逆向分析。
分析:eval混淆,查看eval函数定义:

定义函数,并执行,查看返回的数据:

查看返回的数据(与spa7、spa8一致):

spa10
JJ解密加密:http://www.liminba.com/tool/jjencode/
案例spa10:NBA 球星数据网站,数据纯前端渲染,Token 经过加密处理,JavaScript 经过JJEncode 混淆,适合 JavaScript 逆向分析。
分析:JJEncode混淆,包含很多$,常见就是Function自执行函数,去掉代码最后的()并在控制台输出,即可进入虚拟机显示明文代码;也可以使用加密解密网站。

双击输出的结果,进入虚拟机查看明文代码

spa11
AA加密解密:
案例spa11:NBA 球星数据网站,数据纯前端渲染,Token 经过加密处理,JavaScript 经过AAEncode 混淆,适合 JavaScript 逆向分析。
分析:AAEncode 混淆,包含很多颜文字符号,处理方法同上;也可以使用加密解密网站。

双击输出的结果,进入虚拟机查看明文代码

spa12
JSFuck解密:http://www.liminba.com/tool/jsfuckdecode/
案例spa12:NBA 球星数据网站,数据纯前端渲染,Token 经过加密处理,JavaScript经过JSFuck 混淆,适合 JavaScript 逆向分析。
分析:JSFuck混淆,包含很多[],处理方法与上方相似,注意处理最后一个括号。可以复制到IDE工具中比较好找到对应的正括号;也可以使用解密网站。

spa13
案例spa13:NBA 球星数据网站,数据纯前端渲染,Token 经过加密处理,JavaScript 经过JavaScript Obfuscator 混淆,适合JavaScript 逆向分析。
分析:JavaScript Obfuscator 混淆,包含很多_0x数字字母,理解难度大。
这里暂时跳过…后续变强再回来!
spa14
案例spa14:电影数据网站,数据通过 Ajax 加载,数据接口参数加密且有时间限制,加密过程通过数值型 WASM 实现,适合 WASM 逆向分析。
分析:WebAssembly (简称Wasm) 是一种新型的低级二进制格式,为现代Web应用程序提供高性能的执行环境。wasm 是js可执行的一个扩展文件,我们使用python模拟执行此文件进行逆向分析。
将此wasm文件另存到本地。

断点进行分析

import time
import pywasm
'''
ScrapeCenter spa14
'''
def encrypt(n,t):
runtime = pywasm.core.Runtime()
m = runtime.instance_from_file('./js/Wasm.wasm')
sign = runtime.invocate(m, 'encrypt', [n, t])
# 得到的sign是一个数组,可以在这返回指定下标得到具体值
return sign[0]
def get_sign():
for n in range(1,11):
t = int(time.time())
sign = encrypt(n,t)
print(f"第{n}页的sign为{sign}")
if __name__ == '__main__':
get_sign()
spa15
spa15这里参考:https://blog.csdn.net/weixin_42065546/article/details/145586249
案例spa15:电影数据网站,数据通过 Ajax 加载,数据接口参数加密且有时间限制,加密过程通过字符串型 WASM 实现,适合 WASM 逆向分析。
分析:断点调试没有成功,参考了实现过程,最后逆向成功。
import base64
import hashlib
import requests
import time
'''
ScrapeCenter spa15
'''
uri = '/api/movie'
timestamp = int(time.time())
hashhex = hashlib.sha1(f'{uri},{timestamp}'.encode('utf-8')).hexdigest()
sign = base64.b64encode(f'{hashhex},{timestamp}'.encode('utf-8'))
print('sign: ', sign.decode('utf-8'))
token = sign.decode('utf-8')
url = f"https://spa15.scrape.center/api/movie?limit=10&offset=10&token={token}"
res = requests.get(url)
print(res.status_code)
print(res.text)
spa16
httpx官方在线文档:https://www.python-httpx.org/http2/
案例spa16:图书网站,无反爬,不同于其他,该网站协议采用 HTTP 2,适合用于 HTTP 2 协议分析和测试。
分析:python中requests库支持HTTP1.x,并不支持HTTP2,所以我们需要使用支持HTTP2的库HTTPX,使用终端安装httpx,请在终端命令行执行:pip install httpx[http2]
import httpx
'''
ScrapeCenter spa16
'''
url = 'https://spa16.scrape.center/api/book/'
client = httpx.Client(http2=True)
res = client.get(url)
print(res.text)
data = res.json()
for data in data["results"]:
print(data)
captcha1
案例网址:https://captcha1.scrape.center/
案例:对接滑动拼图验证码,适合滑动拼图验证码分析处理。
分析:使用Selenium自动化,由于这里不能直接下载验证码图片,使用元素的screenshot方法进行截图保存,并分别计算缺口、滑块的x轴距离,结合ActionChains实现模拟连续的鼠标操作,模拟人类“先快后慢”的拖动轨迹,提高验证通过率。当然这种情况不能够实现100%通过。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from PIL import Image
import time
# 获取滑块、缺口以及完整图
def get_img():
# (1)隐藏滑块 得到缺口图
js_hide_hk = 'document.getElementsByClassName("geetest_canvas_slice")[0].style.display="none"'
driver.execute_script(js_hide_hk)
# 截取缺口图
qk_img = "./img/captcha1-qk.png"
driver.find_element(By.CLASS_NAME, "geetest_canvas_bg").screenshot(qk_img)
# (2)显示滑块 隐藏缺口图 得到滑块图
js_show_hk = 'document.getElementsByClassName("geetest_canvas_slice")[0].style.display="block"'
js_hide_qk = 'document.getElementsByClassName("geetest_canvas_bg")[0].style.display="none"'
driver.execute_script(js_show_hk + ";" + js_hide_qk)
# 截取滑块图
hk_img = "./img/captcha1-hk.png"
driver.find_element(By.CLASS_NAME, "geetest_canvas_slice").screenshot(hk_img)
# (3)显示完整图
js_show_wz1 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="block"'
js_show_wz2 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity="1"'
driver.execute_script(js_show_wz1 + ";" + js_show_wz2)
# 截取完整图
wz_img = "./img/captcha1-wz.png"
driver.find_element(By.CLASS_NAME, "geetest_canvas_fullbg").screenshot(wz_img)
# 还原 目的 还原成原来的模样 包含缺口图与滑块
js_hide_wz1 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="none"'
js_hide_wz2 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity="0"'
js_show_qk = 'document.getElementsByClassName("geetest_canvas_bg")[0].style.display="block"'
driver.execute_script(js_hide_wz1 + ";" + js_hide_wz2 + ";" + js_show_qk)
return hk_img, qk_img, wz_img
# 获取滑块的x轴坐标
def get_hk_x(hk_img):
hk = Image.open(hk_img)
w, h = hk.size
for x in range(w):
for y in range(h):
rgb = hk.getpixel((x, y)) # (255,255,255)
if rgb[0] + rgb[1] + rgb[2] < 600:
print("滑块的坐标", x)
return x
# 获取缺口的x轴坐标
def get_qk_x(qk_img, wz_img):
qk = Image.open(qk_img)
wz = Image.open(wz_img)
w, h = qk.size
for x in range(w):
for y in range(h):
qk_point = qk.getpixel((x, y))
wz_point = wz.getpixel((x, y))
r = qk_point[0] - wz_point[0]
g = qk_point[1] - wz_point[1]
b = qk_point[2] - wz_point[2]
abs_value = abs(r) + abs(g) + abs(b) # 33
if abs_value > 180:
print("缺口的坐标", x)
return x
# 计算滑动距离
def get_distance(hk_img, qk_img, wz_img):
hk_x = get_hk_x(hk_img)
qk_x = get_qk_x(qk_img, wz_img)
data = abs(hk_x - qk_x)
print('计算距离', data)
return data
# 滑动
def move(tracks):
# 确定滑块对象
element = driver.find_element(by=By.CLASS_NAME, value='geetest_slider_button')
action_chains = ActionChains(driver)
# 执行滑块的动作
action_chains.click_and_hold(element).perform()
action_chains.pause(0.2)
action_chains.move_by_offset(tracks - 10, 0) #
action_chains.pause(0.6)
action_chains.move_by_offset(10, 0) #
action_chains.pause(0.6)
action_chains.release().perform()
if __name__ == '__main__':
driver = webdriver.Chrome()
url = 'https://captcha1.scrape.center/'
driver.get(url)
driver.find_elements(By.CLASS_NAME, 'el-input__inner')[0].send_keys("admin")
driver.find_elements(By.CLASS_NAME, 'el-input__inner')[1].send_keys("admin")
# 需要等待一下,太快点击不弹验证
time.sleep(2)
driver.find_element(By.XPATH, '//*[@id="app"]/div[2]/div/div/div/div/div/form/div[3]/div/button').click()
# 等待页面滑块元素出现
(WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'geetest_wrap'))))
hk_img, qk_img, wz_img = get_img()
distance = get_distance(hk_img, qk_img, wz_img)
move(distance)
time.sleep(2)
# 获取当前URL
current_url = driver.current_url
# 使用assert断言URL是否正确
expected_url = "https://captcha1.scrape.center/success"
assert current_url == expected_url, f"URL不匹配: 预期 {expected_url}, 实际 {current_url}"
print("模拟登录完成!!!!")
time.sleep(5)
driver.quit()
captcha7
案例captcha7:对接普通图像验证码,干扰较少,适合OCR 识别。
分析:使用selenium完成自动化操作,pillow库读取img,tesserocr进行OCR识别,这里需要注意验证码识别并不是很准确,需要结合图像灰度处理或二值化可能会提高准确率。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from PIL import Image
import tesserocr
'''
ScrapeCenter captcha17
'''
driver = webdriver.Chrome()
url = 'https://captcha7.scrape.center/'
driver.get(url)
time.sleep(2) # 这里需要有一个停顿
driver.find_elements(By.CLASS_NAME,"el-input__inner")[0].send_keys("admin")
driver.find_elements(By.CLASS_NAME,"el-input__inner")[1].send_keys("admin")
# 获取验证码图片
img = "./captcha7.png"
driver.find_element(By.ID,"captcha").screenshot(img)
image = Image.open(img)
key = tesserocr.image_to_text(image)
print(key)
driver.find_elements(By.CLASS_NAME,"el-input__inner")[2].send_keys(key)
driver.find_element(By.XPATH,'//*[@id="app"]/div[2]/div/div/div/div/div/form/div[4]/div/button').click()
# 获取当前URL
current_url = driver.current_url
# 使用assert断言URL是否正确
expected_url = "https://captcha7.scrape.center/success"
assert current_url == expected_url, f"URL不匹配: 预期 {expected_url}, 实际 {current_url}"
antispider1
案例网址:https://antispider1.scrape.center/
案例:对接 WebDriver反爬,检测到使用WebDriver 就不显示页面,适合用作WebDriver 反爬练习。
分析:WebDriver反爬虫解决方案
import time
from selenium import webdriver
driver = webdriver.Chrome()
with open('./js/stealth.min.js', encoding='utf-8') as f:
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {'source': f.read()}) # 在页面刚加载的时候执行JavaScript语句
url = 'https://antispider1.scrape.center/'
driver.get(url)
time.sleep(2)
print(driver.page_source)
antispider2
案例网址:https://antispider2.scrape.center/
案例:对接 User-Agent 反爬,检测到常见爬虫User-Agent 就会拒绝响应,适合用作 User-Agent 反爬练习。
分析:User-Agent反爬虫解决方案
import requests
url = 'https://antispider2.scrape.center/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}
response = requests.get(url, headers=headers)
print(response.text)
antispider3
案例网址:https://antispider3.scrape.center/
案例:对接文字偏移反爬,所见顺序并不一定和源码顺序一致,适合用作文字偏移反爬练习。
分析:selenium自动化结合pyquery网页解析,提取到所有的书名
import re
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from pyquery import PyQuery as pq
def parse(name):
# 找到该h3下每个span的class名为char
char = name(".char")
results = []
for char in char.items():
# 追加到列表中为字典,形成映射
results.append({"text": char.text().strip(),"left": int(re.search(r'left: (\d+)', char.attr('style')).group(1))})
# 按照left键进行排序
results = sorted(results, key=lambda i:i["left"], reverse=False)
# 列表推导式将每个值拼接成完整的书名
return ''.join([result.get('text') for result in results])
driver = webdriver.Chrome()
driver.get('https://antispider3.scrape.center/')
(WebDriverWait(driver,10).until(ec.presence_of_all_elements_located((By.CSS_SELECTOR,'.item'))))
html = driver.page_source
doc = pq(html)
# 获取class为 item .name
names = doc('.item .name')
print(len(names))
for name in names.items():
if name(".char"):
names = parse(name)
print(names)
else:
print(name.text())
antispider4
案例网址:https://antispider4.scrape.center/
案例:对接字体文件反爬,显示的内容并不在HTML 内,而是隐藏在字体文件,设置了文字映射表,适合用作字体反爬练习。
分析:正常使用selenium可以爬取到数据,但是发现电影评分获取不到,针对电影评分做了文字字体反爬,需要解析出css对应的关系映射。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import re
import requests
# 这里解析css文件,找出对应的映射关系
response = requests.get('https://antispider4.scrape.center/css/app.654ba59e.css')
# 使用正则表达式匹配所有的目标规则
# ([\w-]+):捕获组1,匹配.icon-后的字母、数字或字符(如281、A),\w等价于[a-zA-Z0-9_]。
# "([^"]+)":捕获组2,匹配双引号内的任意非引号字符(如"3"、".")。
# \s*:匹配任意空白(空格、换行),增强对CSS格式变化的适应性
pattern = r'\.icon-([\w-]+):before\s*{\s*content:\s*"([^"]+)"\s*}'
results = re.findall(pattern, response.text)
# 构建字典
final_results = {item[0]: item[1] for item in results}
print(final_results)
driver = webdriver.Chrome()
driver.get('https://antispider4.scrape.center/')
(WebDriverWait(driver, 10)
.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.item'))))
# 找到所有图书的div标签列表
data_list = driver.find_elements(By.XPATH, '//*[@id="index"]/div[1]/div[1]/div')
for d in data_list:
print(d.text)
# 找到span标签
i = d.find_elements(By.XPATH, './/div/div/div[3]/p[1]/span')
score = ''
# 遍历每个span标签下的i标签
for j in i:
icon = j.find_element(By.XPATH,'.//i').get_attribute("class")
# 直接匹配连字符后的数字
match = re.search(r'icon-(\d+)', icon)
if match:
number = match.group(1)
# 把键传入字典,得到值进行累加拼接
name = final_results[number]
score += name
print(score)
driver.close()
driver.quit()
antispider9
案例网址:https://antispider9.scrape.center/
案例:对接字体文件反爬,显示的内容并不在HTML 内,而是隐藏在字体文件,设置了文字映射表,适合用作字体反爬练习。
分析:固定值:/api/movie与时间 r 合成数组n进行,拼接得到数据:“/api/movie,{r}” ,使用sha1加密得到c,c与时间r拼接成:“{c},{r}”,进行base64数据格式转换得到a

from hashlib import sha1
import base64
t = '1749710971'
r = f"/api/movie,{t}"
sha1_encode = sha1(r.encode('utf-8')).hexdigest()
data= f'{sha1_encode},{t}'
token = base64.b64encode(data.encode()).decode()
print(token)
更多推荐
所有评论(0)