初始版本发布

This commit is contained in:
杨志
2026-01-20 14:12:19 +08:00
parent 6e0c3ae1a0
commit 871aefc33e
4 changed files with 1051 additions and 0 deletions

285
app/controller/Crawler.php Normal file
View File

@@ -0,0 +1,285 @@
<?php
declare (strict_types = 1);
namespace app\controller;
use app\BaseController;
use app\service\CrawlerService;
use think\facade\View;
/**
* 爬虫控制器
*/
class Crawler extends BaseController
{
/**
* 显示爬虫工具首页
*/
public function index()
{
return View::fetch();
}
/**
* 获取地区选项从网页HTML中提取
*/
public function getDsdmOptions()
{
try {
$examid = $this->request->param('examid', '');
$bmid = $this->request->param('bmid', '');
$userid = $this->request->param('userid', '');
if (empty($examid) || empty($bmid) || empty($userid)) {
return json([
'code' => 0,
'msg' => '请先填写examid、bmid和userid',
]);
}
// 构建URL获取HTML
$url = "http://gzrsks.oumakspt.com:62/tyzpwb/stuchooseexam/selectPosition.htm?examstupid=1015&userid={$userid}&bmid={$bmid}&examid={$examid}&aa=" . time() . '000';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$html = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return json([
'code' => 0,
'msg' => '获取网页失败: ' . $error,
]);
}
if ($httpCode !== 200) {
return json([
'code' => 0,
'msg' => '获取网页失败HTTP状态码: ' . $httpCode,
]);
}
$service = new CrawlerService();
$options = $service->extractDsdmOptions($html);
return json([
'code' => 1,
'data' => $options,
'msg' => '获取成功',
]);
} catch (\Exception $e) {
return json([
'code' => 0,
'msg' => '获取失败: ' . $e->getMessage(),
]);
}
}
/**
* 获取职位代码列表
*/
public function getZwdmList()
{
try {
$dsdm = $this->request->param('dsdm', '');
$cookiesParam = $this->request->param('cookies', '');
if (empty($dsdm)) {
return json([
'code' => 0,
'msg' => '请选择地区',
]);
}
if (empty($cookiesParam)) {
return json([
'code' => 0,
'msg' => '请填写Cookie数据',
]);
}
// 解析JSON格式的cookies
$cookies = is_string($cookiesParam) ? json_decode($cookiesParam, true) : $cookiesParam;
if (json_last_error() !== JSON_ERROR_NONE || empty($cookies)) {
return json([
'code' => 0,
'msg' => 'Cookie数据格式错误请检查JSON格式',
]);
}
$service = new CrawlerService();
$treeData = $service->getPositionTree($dsdm, $cookies);
// 提取所有CODE作为zwdm
$zwdmList = [];
if (is_array($treeData)) {
foreach ($treeData as $item) {
if (isset($item['CODE']) && !empty($item['CODE'])) {
$zwdmList[] = [
'zwdm' => $item['CODE'],
'title' => $item['TITLE'] ?? $item['CODE'],
];
}
}
}
return json([
'code' => 1,
'data' => $zwdmList,
'msg' => '获取成功',
]);
} catch (\Exception $e) {
return json([
'code' => 0,
'msg' => '获取失败: ' . $e->getMessage(),
]);
}
}
/**
* 获取职位详细信息
*/
public function getPositionInfo()
{
try {
$zwdm = $this->request->param('zwdm', '');
$examid = $this->request->param('examid', '');
$cookiesParam = $this->request->param('cookies', '');
if (empty($zwdm) || empty($examid)) {
return json([
'code' => 0,
'msg' => '参数不完整',
]);
}
if (empty($cookiesParam)) {
return json([
'code' => 0,
'msg' => '请填写Cookie数据',
]);
}
// 解析JSON格式的cookies
$cookies = is_string($cookiesParam) ? json_decode($cookiesParam, true) : $cookiesParam;
if (json_last_error() !== JSON_ERROR_NONE || empty($cookies)) {
return json([
'code' => 0,
'msg' => 'Cookie数据格式错误请检查JSON格式',
]);
}
$service = new CrawlerService();
$info = $service->getPositionInfo($zwdm, $examid, $cookies);
if (!empty($info)) {
// 处理单条数据或数组数据
if (isset($info[0])) {
$item = $info[0];
} else {
$item = $info;
}
// 计算竞争比
$zprs = isset($item['zprs']) ? intval($item['zprs']) : 0;
$bkrs = isset($item['bkrs']) ? intval($item['bkrs']) : 0;
$competitionRatio = $zprs > 0 ? ($bkrs / $zprs) : 0;
$result = [
'sbmc' => $item['sbmc'] ?? '', // 省份
'dsmc' => $item['dsmc'] ?? '', // 地区
'zpdwmc' => $item['zpdwmc'] ?? '', // 招聘单位/用人司局
'zwmc' => $item['zwmc'] ?? '', // 职位名称
'zwdm' => $item['zwdm'] ?? $zwdm, // 职位代码
'zprs' => $zprs, // 招聘人数
'bkrs' => $bkrs, // 审核通过人数
'competition_ratio' => number_format($competitionRatio, 2), // 竞争比
];
return json([
'code' => 1,
'data' => $result,
'msg' => '获取成功',
]);
} else {
return json([
'code' => 0,
'msg' => '未获取到数据',
]);
}
} catch (\Exception $e) {
return json([
'code' => 0,
'msg' => '获取失败: ' . $e->getMessage(),
]);
}
}
/**
* 批量获取职位信息
*/
public function batchGetPositionInfo()
{
try {
$zwdmListParam = $this->request->param('zwdm_list', '');
$examid = $this->request->param('examid', '');
$cookiesParam = $this->request->param('cookies', '');
// 解析JSON格式的zwdm_list
$zwdmList = is_string($zwdmListParam) ? json_decode($zwdmListParam, true) : $zwdmListParam;
if (json_last_error() !== JSON_ERROR_NONE || empty($zwdmList) || !is_array($zwdmList)) {
return json([
'code' => 0,
'msg' => '请选择职位代码',
]);
}
if (empty($examid)) {
return json([
'code' => 0,
'msg' => '请填写examid',
]);
}
if (empty($cookiesParam)) {
return json([
'code' => 0,
'msg' => '请填写Cookie数据',
]);
}
// 解析JSON格式的cookies
$cookies = is_string($cookiesParam) ? json_decode($cookiesParam, true) : $cookiesParam;
if (json_last_error() !== JSON_ERROR_NONE || empty($cookies)) {
return json([
'code' => 0,
'msg' => 'Cookie数据格式错误请检查JSON格式',
]);
}
$service = new CrawlerService();
$results = $service->batchGetPositionInfo($zwdmList, $examid, $cookies);
return json([
'code' => 1,
'data' => $results,
'msg' => '获取成功',
]);
} catch (\Exception $e) {
return json([
'code' => 0,
'msg' => '获取失败: ' . $e->getMessage(),
]);
}
}
}

View File

@@ -0,0 +1,216 @@
<?php
declare (strict_types = 1);
namespace app\service;
/**
* 爬虫服务类
* 用于处理职位信息爬取相关逻辑
*/
class CrawlerService
{
/**
* 基础URL
*/
private $baseUrl = 'http://gzrsks.oumakspt.com:62/tyzpwb';
/**
* 获取职位树数据
* @param string $dsdm 地区代码
* @param array $cookies Cookie数据
* @return array
*/
public function getPositionTree(string $dsdm, array $cookies): array
{
$url = $this->baseUrl . '/tree/getPositionTree.htm';
$cookieString = $this->buildCookieString($cookies);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Cookie: ' . $cookieString,
'Content-Type: application/x-www-form-urlencoded',
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['dsdm' => $dsdm]));
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new \Exception('请求失败: ' . $error);
}
if ($httpCode !== 200) {
throw new \Exception('请求失败HTTP状态码: ' . $httpCode);
}
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \Exception('JSON解析失败: ' . json_last_error_msg());
}
return $data ?: [];
}
/**
* 获取职位详细信息
* @param string $zwdm 职位代码
* @param string $examid 考试ID
* @param array $cookies Cookie数据
* @return array
*/
public function getPositionInfo(string $zwdm, string $examid, array $cookies): array
{
$url = $this->baseUrl . '/stuchooseexam/getPositionInfo.htm';
$cookieString = $this->buildCookieString($cookies);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Cookie: ' . $cookieString,
'Content-Type: application/x-www-form-urlencoded',
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'zwdm' => $zwdm,
'examid' => $examid
]));
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new \Exception('请求失败: ' . $error);
}
if ($httpCode !== 200) {
throw new \Exception('请求失败HTTP状态码: ' . $httpCode);
}
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \Exception('JSON解析失败: ' . json_last_error_msg());
}
return $data ?: [];
}
/**
* 批量获取职位信息
* @param array $zwdmList 职位代码列表
* @param string $examid 考试ID
* @param array $cookies Cookie数据
* @return array
*/
public function batchGetPositionInfo(array $zwdmList, string $examid, array $cookies): array
{
$results = [];
foreach ($zwdmList as $zwdm) {
try {
$info = $this->getPositionInfo($zwdm, $examid, $cookies);
if (!empty($info)) {
// 处理单条数据或数组数据
if (isset($info[0])) {
$item = $info[0];
} else {
$item = $info;
}
// 计算竞争比
$zprs = isset($item['zprs']) ? intval($item['zprs']) : 0;
$bkrs = isset($item['bkrs']) ? intval($item['bkrs']) : 0;
$competitionRatio = $zprs > 0 ? ($bkrs / $zprs) : 0;
$results[] = [
'sbmc' => $item['sbmc'] ?? '', // 省份
'dsmc' => $item['dsmc'] ?? '', // 地区
'zpdwmc' => $item['zpdwmc'] ?? '', // 招聘单位/用人司局
'zwmc' => $item['zwmc'] ?? '', // 职位名称
'zwdm' => $item['zwdm'] ?? $zwdm, // 职位代码
'zprs' => $zprs, // 招聘人数
'bkrs' => $bkrs, // 审核通过人数
'competition_ratio' => number_format($competitionRatio, 2), // 竞争比
];
}
// 避免请求过快,添加小延迟
usleep(200000); // 0.2秒
} catch (\Exception $e) {
// 记录错误但继续处理其他数据
$results[] = [
'zwdm' => $zwdm,
'error' => $e->getMessage(),
];
}
}
return $results;
}
/**
* 构建Cookie字符串
* @param array $cookies Cookie数组
* @return string
*/
private function buildCookieString(array $cookies): string
{
$cookieArray = [];
// 处理嵌套的Cookie结构
if (isset($cookies['请求 Cookie'])) {
$cookieData = $cookies['请求 Cookie'];
} else {
$cookieData = $cookies;
}
foreach ($cookieData as $key => $value) {
$cookieArray[] = $key . '=' . $value;
}
return implode('; ', $cookieArray);
}
/**
* 从HTML中提取地区选项
* @param string $html HTML内容
* @return array
*/
public function extractDsdmOptions(string $html): array
{
$options = [];
// 使用正则表达式提取option标签
preg_match_all('/<option\s+value="([^"]+)"[^>]*>([^<]+)<\/option>/i', $html, $matches);
if (!empty($matches[1])) {
foreach ($matches[1] as $index => $value) {
if (!empty($value)) { // 跳过"请选择"等空值
$options[] = [
'value' => $value,
'text' => $matches[2][$index] ?? $value,
];
}
}
}
return $options;
}
}

View File

@@ -15,3 +15,10 @@ Route::get('think', function () {
}); });
Route::get('hello/:name', 'index/hello'); Route::get('hello/:name', 'index/hello');
// 爬虫工具路由
Route::get('crawler', 'crawler/index');
Route::post('crawler/getDsdmOptions', 'crawler/getDsdmOptions');
Route::post('crawler/getZwdmList', 'crawler/getZwdmList');
Route::post('crawler/getPositionInfo', 'crawler/getPositionInfo');
Route::post('crawler/batchGetPositionInfo', 'crawler/batchGetPositionInfo');

543
view/crawler/index.html Normal file
View File

@@ -0,0 +1,543 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>职位信息爬虫工具</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: #f5f5f5;
padding: 20px;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
padding: 30px;
}
h1 {
color: #333;
margin-bottom: 30px;
text-align: center;
font-size: 24px;
}
.form-section {
margin-bottom: 30px;
padding: 20px;
background: #f9f9f9;
border-radius: 6px;
border: 1px solid #e0e0e0;
}
.form-section h2 {
font-size: 18px;
color: #555;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 2px solid #4CAF50;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
color: #333;
font-weight: 500;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.form-group textarea {
min-height: 100px;
font-family: monospace;
resize: vertical;
}
.form-group small {
display: block;
margin-top: 5px;
color: #666;
font-size: 12px;
}
.btn {
padding: 10px 20px;
background: #4CAF50;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background 0.3s;
}
.btn:hover {
background: #45a049;
}
.btn:disabled {
background: #ccc;
cursor: not-allowed;
}
.btn-secondary {
background: #2196F3;
}
.btn-secondary:hover {
background: #0b7dda;
}
.btn-danger {
background: #f44336;
}
.btn-danger:hover {
background: #da190b;
}
.checkbox-group {
max-height: 300px;
overflow-y: auto;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
background: #fff;
}
.checkbox-item {
padding: 8px;
border-bottom: 1px solid #f0f0f0;
}
.checkbox-item:last-child {
border-bottom: none;
}
.checkbox-item label {
display: flex;
align-items: center;
cursor: pointer;
}
.checkbox-item input[type="checkbox"] {
width: auto;
margin-right: 8px;
}
.message {
padding: 12px;
border-radius: 4px;
margin-bottom: 15px;
}
.message.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.message.info {
background: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
.table-container {
margin-top: 30px;
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
background: #fff;
}
table th,
table td {
padding: 12px;
text-align: left;
border: 1px solid #ddd;
}
table th {
background: #4CAF50;
color: #fff;
font-weight: 600;
position: sticky;
top: 0;
}
table tr:nth-child(even) {
background: #f9f9f9;
}
table tr:hover {
background: #f0f0f0;
}
.loading {
text-align: center;
padding: 20px;
color: #666;
}
.loading::after {
content: '...';
animation: dots 1.5s steps(4, end) infinite;
}
@keyframes dots {
0%, 20% { content: '.'; }
40% { content: '..'; }
60%, 100% { content: '...'; }
}
.action-buttons {
display: flex;
gap: 10px;
margin-top: 15px;
}
.select-all {
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>职位信息爬虫工具</h1>
<!-- 第一步:填写基础信息 -->
<div class="form-section">
<h2>第一步:填写基础信息</h2>
<div class="form-group">
<label for="cookies">Cookie数据JSON格式</label>
<textarea id="cookies" placeholder='{"请求 Cookie": {"JSESSIONID": "xxx", "SERVERID": "xxx"}}'></textarea>
<small>请填写完整的Cookie数据格式为JSON</small>
</div>
<div class="form-group">
<label for="examid">examid</label>
<input type="text" id="examid" placeholder="796a0fa25f7c9ffb">
</div>
<div class="form-group">
<label for="bmid">bmid</label>
<input type="text" id="bmid" placeholder="b9cd1e7ea77ed17a">
</div>
<div class="form-group">
<label for="userid">userid</label>
<input type="text" id="userid" placeholder="9be05723b21f7c51">
</div>
<div class="action-buttons">
<button class="btn btn-secondary" onclick="getDsdmOptions()">获取地区选项</button>
</div>
</div>
<!-- 第二步:选择地区 -->
<div class="form-section">
<h2>第二步:选择地区</h2>
<div id="dsdm-message"></div>
<div class="form-group">
<label for="dsdm">地区代码dsdm</label>
<select id="dsdm">
<option value="">请先获取地区选项</option>
</select>
</div>
<div class="action-buttons">
<button class="btn btn-secondary" onclick="getZwdmList()">获取职位代码列表</button>
</div>
</div>
<!-- 第三步:选择职位代码 -->
<div class="form-section">
<h2>第三步:选择职位代码</h2>
<div id="zwdm-message"></div>
<div class="form-group">
<div class="select-all">
<label>
<input type="checkbox" id="select-all-zwdm" onchange="toggleAllZwdm()">
全选/取消全选
</label>
</div>
<div class="checkbox-group" id="zwdm-list">
<div class="loading">请先获取职位代码列表</div>
</div>
</div>
<div class="action-buttons">
<button class="btn" onclick="batchGetPositionInfo()">批量获取职位信息</button>
</div>
</div>
<!-- 结果显示 -->
<div class="form-section">
<h2>职位信息结果</h2>
<div id="result-message"></div>
<div class="table-container" id="result-table" style="display: none;">
<table id="data-table">
<thead>
<tr>
<th>省份</th>
<th>地区</th>
<th>招聘单位/用人司局</th>
<th>职位名称</th>
<th>职位代码</th>
<th>招聘人数</th>
<th>审核通过人数</th>
<th>竞争比</th>
</tr>
</thead>
<tbody id="data-table-body">
</tbody>
</table>
</div>
</div>
</div>
<script>
// 获取地区选项
function getDsdmOptions() {
const examid = document.getElementById('examid').value.trim();
const bmid = document.getElementById('bmid').value.trim();
const userid = document.getElementById('userid').value.trim();
if (!examid || !bmid || !userid) {
showMessage('dsdm-message', '请先填写examid、bmid和userid', 'error');
return;
}
showMessage('dsdm-message', '正在获取地区选项...', 'info');
fetch('/crawler/getDsdmOptions', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `examid=${encodeURIComponent(examid)}&bmid=${encodeURIComponent(bmid)}&userid=${encodeURIComponent(userid)}`
})
.then(response => response.json())
.then(data => {
if (data.code === 1) {
const select = document.getElementById('dsdm');
select.innerHTML = '<option value="">请选择</option>';
data.data.forEach(option => {
const opt = document.createElement('option');
opt.value = option.value;
opt.textContent = option.text;
select.appendChild(opt);
});
showMessage('dsdm-message', '获取地区选项成功,请选择地区', 'success');
} else {
showMessage('dsdm-message', data.msg || '获取失败', 'error');
}
})
.catch(error => {
showMessage('dsdm-message', '请求失败: ' + error.message, 'error');
});
}
// 获取职位代码列表
function getZwdmList() {
const dsdm = document.getElementById('dsdm').value;
const cookies = document.getElementById('cookies').value.trim();
if (!dsdm) {
showMessage('zwdm-message', '请先选择地区', 'error');
return;
}
if (!cookies) {
showMessage('zwdm-message', '请先填写Cookie数据', 'error');
return;
}
let cookieData;
try {
cookieData = JSON.parse(cookies);
} catch (e) {
showMessage('zwdm-message', 'Cookie数据格式错误请检查JSON格式', 'error');
return;
}
showMessage('zwdm-message', '正在获取职位代码列表...', 'info');
fetch('/crawler/getZwdmList', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `dsdm=${encodeURIComponent(dsdm)}&cookies=${encodeURIComponent(JSON.stringify(cookieData))}`
})
.then(response => response.json())
.then(data => {
if (data.code === 1) {
const container = document.getElementById('zwdm-list');
container.innerHTML = '';
if (data.data.length === 0) {
container.innerHTML = '<div class="loading">未找到职位代码</div>';
showMessage('zwdm-message', '未找到职位代码', 'info');
return;
}
data.data.forEach(item => {
const div = document.createElement('div');
div.className = 'checkbox-item';
div.innerHTML = `
<label>
<input type="checkbox" value="${item.zwdm}" class="zwdm-checkbox">
${item.title}
</label>
`;
container.appendChild(div);
});
showMessage('zwdm-message', `获取成功,共找到 ${data.data.length} 个职位代码`, 'success');
} else {
showMessage('zwdm-message', data.msg || '获取失败', 'error');
}
})
.catch(error => {
showMessage('zwdm-message', '请求失败: ' + error.message, 'error');
});
}
// 全选/取消全选
function toggleAllZwdm() {
const selectAll = document.getElementById('select-all-zwdm').checked;
const checkboxes = document.querySelectorAll('.zwdm-checkbox');
checkboxes.forEach(checkbox => {
checkbox.checked = selectAll;
});
}
// 批量获取职位信息
function batchGetPositionInfo() {
const examid = document.getElementById('examid').value.trim();
const cookies = document.getElementById('cookies').value.trim();
if (!examid) {
showMessage('result-message', '请先填写examid', 'error');
return;
}
if (!cookies) {
showMessage('result-message', '请先填写Cookie数据', 'error');
return;
}
let cookieData;
try {
cookieData = JSON.parse(cookies);
} catch (e) {
showMessage('result-message', 'Cookie数据格式错误请检查JSON格式', 'error');
return;
}
const checkboxes = document.querySelectorAll('.zwdm-checkbox:checked');
if (checkboxes.length === 0) {
showMessage('result-message', '请至少选择一个职位代码', 'error');
return;
}
const zwdmList = Array.from(checkboxes).map(cb => cb.value);
showMessage('result-message', `正在获取 ${zwdmList.length} 个职位的信息,请稍候...`, 'info');
fetch('/crawler/batchGetPositionInfo', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `examid=${encodeURIComponent(examid)}&zwdm_list=${encodeURIComponent(JSON.stringify(zwdmList))}&cookies=${encodeURIComponent(JSON.stringify(cookieData))}`
})
.then(response => response.json())
.then(data => {
if (data.code === 1) {
displayResults(data.data);
showMessage('result-message', `成功获取 ${data.data.length} 条职位信息`, 'success');
} else {
showMessage('result-message', data.msg || '获取失败', 'error');
}
})
.catch(error => {
showMessage('result-message', '请求失败: ' + error.message, 'error');
});
}
// 显示结果表格
function displayResults(results) {
const tbody = document.getElementById('data-table-body');
tbody.innerHTML = '';
results.forEach(item => {
if (item.error) {
const tr = document.createElement('tr');
tr.innerHTML = `
<td colspan="8" style="color: red;">职位代码 ${item.zwdm}: ${item.error}</td>
`;
tbody.appendChild(tr);
} else {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${item.sbmc || ''}</td>
<td>${item.dsmc || ''}</td>
<td>${item.zpdwmc || ''}</td>
<td>${item.zwmc || ''}</td>
<td>${item.zwdm || ''}</td>
<td>${item.zprs || 0}</td>
<td>${item.bkrs || 0}</td>
<td>${item.competition_ratio || '0.00'}</td>
`;
tbody.appendChild(tr);
}
});
document.getElementById('result-table').style.display = 'block';
}
// 显示消息
function showMessage(containerId, message, type) {
const container = document.getElementById(containerId);
container.innerHTML = `<div class="message ${type}">${message}</div>`;
}
</script>
</body>
</html>