Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions lib/routes/gov/beijing/ghzrzyw/land.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Route } from '@/types';
import ofetch from '@/utils/ofetch';
import { parseDate } from '@/utils/parse-date';

export const route: Route = {
path: '/beijing/land/:tab/:filter?/:limit?',
categories: ['government'],
example: '/gov/beijing/land/tdcjylb',
parameters: { tab: 'tdcjylb: 土地成交一览表', filter: '过滤条件' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['yewu.ghzrzyw.beijing.gov.cn/gwxxfb/tdsc/:tab.html', 'https://yewu.ghzrzyw.beijing.gov.cn/gwxxfb/tdsc/:tab.html'],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not include protocol in source

target: '',
},
],
name: '北京土地拍卖信息',
maintainers: ['sohow'],
handler,
};

async function handler(ctx) {
const { tab, filter = '', limit = 10 } = ctx.req.param();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the common query parameter limit from ctx.req.query() instead

const now = Date.now();
if (limit > 50) {
throw new Error('limit 超过 50');
}
const url = `https://yewu.ghzrzyw.beijing.gov.cn/zkdncms/tdgltdsc/${tab}/esSearchList?t=${now}&page=1&limit=${limit}&landusetype1=&announcetype=&county=&gjz=&_=${now}`;
const res = await ofetch(url, {
headers: {
accept: 'application/json',
},
});

// 从 API 响应中提取相关数据
const items = res.data
.filter((item) => checkFilter(filter, item)) // 过滤逻辑
.map((item) => ({
// 标题
title: item.title,
// 链接
link: `https://yewu.ghzrzyw.beijing.gov.cn/zkdncms/tdgltdsc/esSearchDetail/${item.id}?t=${now}&_=${now}`,
// 正文
description: `项目名称:${item.title} \n 项目位置:${item.landlocation} \n 项目类型:${item.landusetype1DictText} \n 成交时间:${item.chegnJiaoShiJian}`,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\n will be rendered as an empty space instead of a linebreak

guid: item.id,
// 日期
pubDate: parseDate(item.createDateTime),
author: item.jingDeRen,
category: item.landid,
}));

return {
// 源标题
title: '北京土地拍卖信息',
// 源链接
link: url,
// 源文章
item: items,
};
}

function checkFilter(filter: string, data: Record<string, any>): boolean {
// 如果filter为空,直接返回true
if (!filter) {
return true;
}

// 按"-"分割条件组
const conditionGroups = filter.split('-');

// 遍历每个条件组
for (const group of conditionGroups) {
// 按"_"分割条件组中的元素
const parts = group.split('_');
if (parts.length < 2) {
continue;
} // 忽略无效条件组

const [key, ...values] = parts; // 第一个元素为key,剩余为匹配值
const dataValue = data[key]; // 从data中获取对应值

// 如果data中不存在该key,当前条件组不满足
if (dataValue === undefined || dataValue === null) {
return false;
}

const dataValueStr = String(dataValue); // 转换为字符串
let matchFound = false;

// 检查是否包含任意一个匹配值
for (const val of values) {
if (dataValueStr.includes(val)) {
matchFound = true;
break;
}
}

// 当前条件组未匹配则整体不满足
if (!matchFound) {
return false;
}
}

return true;
}
7 changes: 7 additions & 0 deletions lib/routes/gov/beijing/ghzrzyw/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Namespace } from '@/types';

export const namespace: Namespace = {
name: '北京市规划和自然资源委员会',
url: 'ghzrzyw.beijing.gov.cn',
lang: 'zh-CN',
};
123 changes: 123 additions & 0 deletions lib/routes/gov/beijing/zjwxk/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { Route } from '@/types';
import ofetch from '@/utils/ofetch';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';

export const route: Route = {
path: '/beijing/zjwxk/:ddlYT?/:ddlQX?/:rblFWType1?',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Route is not tested in auto route test.

categories: ['government'],
example: '/gov/beijing/zjwxk/1/7_17/q_x',
parameters: {
ddlYT: '用途: -1:--请选择--, 1:普通住宅, 2:公寓, 3:别墅, 4:商业, 5:写字楼, 6:工业厂房, 7:车库, 10:其它, 11:综合, 21:经济适用住房, 31:两限房',
ddlQX: '所属区县: -1:--请选择--, 1:北京市, 2:东城区, 3:西城区, 6:朝阳区, 7:海淀区, 8:丰台区, 9:石景山区, 10:通州区, 11:房山区, 12:顺义区, 13:门头沟区, 14:大兴区, 15:怀柔区, 16:密云区, 17:昌平区, 18:延庆区, 19:平谷区, 22:开发区',
rblFWType1: '期房/现房: q:期房, x:现房',
},
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['bjjs.zjw.beijing.gov.cn/eportal/ui?pageId=307670&isTrue=1'],
target: '',
},
],
name: '北京市住建委新建商品房预售许可公示',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Route name should not be the same as namespace name

name: '北京市住建委新建商品房预售许可公示',

maintainers: ['sohow'],
handler,
};

async function handler(ctx) {
const { ddlYT = '', ddlQX = '', rblFWType1 = '' } = ctx.req.param();
let items: any[] = [];

// 处理区县参数
const qxArray = ddlQX ? ddlQX.split('_').filter(Boolean) : [''];

// 处理房屋类型参数
const fwArray = rblFWType1 ? rblFWType1.split('_').filter(Boolean) : [''];

// 生成所有参数组合
const allCombinations: [string, string][] = [];
for (const qx of qxArray) {
for (const fw of fwArray) {
allCombinations.push([qx, fw]);
}
}

// 并发请求所有组合
const promises = allCombinations.map(([qx, fw]) => requestData(ddlYT, qx, fw));

// 等待所有请求完成并合并结果
const results = await Promise.all(promises);
items = results.flat();

return {
title: '北京市住建委新建商品房预售许可公示',
link: `http://bjjs.zjw.beijing.gov.cn/eportal/ui?pageId=307670&isTrue=1`,
item: items,
};
}

async function requestData(ddlYT: string, ddlQX: string, rblFWType1: string): Promise<any[]> {
const baseUrl = 'http://bjjs.zjw.beijing.gov.cn';
const url = `${baseUrl}/eportal/ui?pageId=307670&isTrue=1`;
const data = {
projectName: '项目名称关键字',
rblFWType: 'q',
txtYS: '',
txtZH: '',
txtCQZH: '证号关键字',
developer: '单位名称关键字',
txtaddress: '地址关键字',
isTrue: '1',
ddlQX,
rblFWType1,
ddlYT,
ddlFW: '-1',
ddlQW: '-1',
ddlHX: '-1',
currentPage: '1',
pageSize: '15',
};
const response = await ofetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams(data),
});
const $ = load(response);

// 从 API 响应中提取相关数据
const items = $('#FDCJYFORM > table:nth-child(4) > tbody > tr:nth-child(2) > td > table > tbody tr')
.toArray()
.filter((item) => {
item = $(item);
const title = $(item).find('a').first().text();
return title !== '';
})
.map((item) => {
item = $(item);
const xm = item.find('a').first();
const nu = item.find('a').eq(1);
const pub = item.find('td').eq(2);

const name = xm.text();
const title = `${name} - ${nu.text()} - ${pub.text()}`;
return {
title,
// `link` 需要一个绝对 URL,但 `a.attr('href')` 返回一个相对 URL。
link: `${baseUrl}/${xm.attr('href')}`,
pubDate: parseDate(pub.text()),
author: nu.text(),
guid: nu.text(),
};
});

return items;
}
7 changes: 7 additions & 0 deletions lib/routes/gov/beijing/zjwxk/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Namespace } from '@/types';

export const namespace: Namespace = {
name: '北京市住建委新建商品房预售许可公示',
url: 'zjw.beijing.gov.cn',
lang: 'zh-CN',
};
Loading