作者itoc.bbs@processor.tfcis.org (核心動力) 看板: plan
標題Re: 請問關於雅虎!奇摩的新聞功能
時間動力核心 (2004/02/12 Thu 12:45:28) Updated: 2006/05/23
※ 引述《segaa.bbs@segaa.com.tw (加班ing)》之銘言:
> 如果說要像無名一樣直接把kimo新聞自動轉到看板上
> 每個分類各開一個版,每天自動執行去抓新聞後直接post到板上
在 ~/run/kimo 下開 12 個目錄,分別是
A/ B/ C/ D/ E/ F/ G/ H/ I/ J/ K/ L/
亦即在工作站上執行以下指令
% mkdir ~/run/kimo
% mkdir ~/run/kimo/A ~/run/kimo/B ~/run/kimo/C ~/run/kimo/D
% mkdir ~/run/kimo/E ~/run/kimo/F ~/run/kimo/G ~/run/kimo/H
% mkdir ~/run/kimo/I ~/run/kimo/J ~/run/kimo/K ~/run/kimo/L
: src/util/Makefile
EXE = .... enews-open
: crontab -e 新增此二行
# 每天 10:30AM 4:30PM 抓奇摩新聞
30 10,16 * * * bin/enews-open
: struct.h 新增下面這段
/* ----------------------------------------------------- */
/* enews-open.c 中運用的資料結構 : 256 bytes */
/* ----------------------------------------------------- */
typedef struct
{
time_t chrono; /* 編號 */
char kind; /* 種類 */
char xname[50]; /* 檔案名稱 */
char link[128]; /* 連結路徑 */
char title[TTLEN + 1]; /* 文章標題 */
} ENEWS;
: util/enews-open.c 新增此程式
/*-------------------------------------------------------*/
/* util/enews-open.c ( NTHU CS MapleBBS Ver 3.10 ) */
/*-------------------------------------------------------*/
/* target : 奇摩新聞更新 */
/* create : 02/01/29 */
/* update : / / */
/* author : itoc.bbs@bbs.tnfsh.tn.edu.tw */
/*-------------------------------------------------------*/
#if 0
本奇摩新聞更新程式需要配合 contab 去抓資料,crontab 如下:
# 每天 10:30AM 4:30PM 抓奇摩新聞
30 10,16 * * * bin/enews-open
要使用 enews-open.c 必須裝有 lynx,注意 lynx 的路徑要和程式吻合。
如果主機需透過 proxy 才能連外的話,那麼要修改 lynx.cfg 的 http_proxy 設定值。
文章檔案放在 run/kimo/
資料來源:Yahoo! 奇摩新聞 http://tw.news.yahoo.com/
#endif
#include "bbs.h"
#define LYNX_PATH "/usr/local/bin/lynx --source" /* lynx 的絕對路徑 */
#define INDEX_FILE "tmp/kimo_index"
#define NEWS_FILE "tmp/kimo_news"
#define YAHOO_URL "http://tw.yahoo.com/me/news/*http://tw.news.yahoo.com/"
/*-------------------------------------------------------*/
/* 文章轉到看板 */
/*-------------------------------------------------------*/
static BCACHE *bshm;
static void
init_bshm()
{
/* itoc.030727: 在開啟 bbsd 之前,應該就要執行過 account,
所以 bshm 應該已設定好 */
bshm = shm_new(BRDSHM_KEY, sizeof(BCACHE));
if (bshm->uptime <= 0) /* bshm 未設定完成 */
exit(0);
}
static void
update_btime(brdname)
char *brdname;
{
BRD *bhdr, *tail;
bhdr = bshm->bcache;
tail = bhdr + bshm->number;
do
{
if (!str_cmp(brdname, bhdr->brdname))
{
bhdr->btime = -1;
break;
}
} while (++bhdr < tail);
}
static int /* 1: 以前就抓過的連結 */
old_link(fold, link)
char *fold;
char *link;
{
int rc = 0;
ENEWS enews;
FILE *fp;
if (fp = fopen(fold, "r"))
{
while (fread(&enews, sizeof(ENEWS), 1, fp) == 1)
{
if (!strcmp(enews.link, link))
{
rc = 1;
break;
}
}
fclose(fp);
}
return rc;
}
static void
post_board(fpath, title, kind)
char *fpath;
char *title;
char kind;
{
char folder[64];
HDR hdr;
char class[12][5] =
{
"政治", "社會", "國際", "兩岸", "財經", "影視",
"體育", "生活", "休閒", "健康", "科技", "新奇"
};
char *board = "KimoNews"; // 轉去 KimoNews 板,自定
brd_fpath(folder, board, FN_DIR);
hdr_stamp(folder, HDR_COPY | 'A', &hdr, fpath);
strcpy(hdr.owner, STR_SYSOP);
strcpy(hdr.nick, SYSOPNICK);
sprintf(hdr.title, "[%s] %.64s", class[kind - 'A'], title);
rec_add(folder, &hdr, sizeof(HDR));
update_btime(board);
}
/*-------------------------------------------------------*/
/* 分析 html */
/*-------------------------------------------------------*/
static int wlen; /* 本行有多少字 */
static int slen; /* 本行有多少半形字 */
static void
foutc(ch, fp)
int ch;
FILE *fp;
{
static int in_tag = 0; /* 1: 在 <tag> 中 */
static int in_chi = 0; /* 1: 前一碼是中文字 */
if (ch == '<')
{
in_tag = 1;
return;
}
if (!in_tag)
{
if (in_chi || ch & 0x80) /* 前一個char或這char是中文字的第一碼 */
in_chi ^= 1;
else /* 如果都不是,表示這char是半形字 */
slen++;
if (wlen >= 60 - slen % 2) /* 一行最多 60 字,若有奇數個半形字,
該行只印 59 字 */
{
fputs("\n ", fp); /* 每行前面都空四格 */
wlen = 0;
/* slen = 0; */
slen = !in_chi; /* 若新的這行第一個char是半形字,slen=1 */
}
fputc(ch, fp);
wlen++;
}
else
{
if (ch == '>')
in_tag = 0;
}
}
static void
fouts(str, fp)
uschar *str;
FILE *fp;
{
int ch;
wlen = 0;
slen = 0;
fputs("\n ", fp); /* 每行前面都空四格 */
while (ch = *str)
{
foutc(ch, fp);
str++;
}
}
static void
html_download(enews, fold) /* 下載文章並轉換為文字檔 */
ENEWS *enews;
char *fold;
{
char *strS, *strE;
char buf[2048]; /* 假設文章每段不會超過 2048 字 */
char fpath[64];
FILE *fpr, *fpw;
int article_begin;
/* 下載文章 */
sprintf(buf, LYNX_PATH " %s > " NEWS_FILE, enews->link);
system(buf);
/* 轉換為文字檔 */
if (fpr = fopen(NEWS_FILE, "r"))
{
sprintf(fpath, "run/kimo/%c/%s", enews->kind, enews->xname);
if (fpw = fopen(fpath, "w"))
{
/* 開頭加上標題 */
fprintf(fpw, "%s %s (%s) %s %s\n",
STR_AUTHOR1, STR_SYSOP, SYSOPNICK, STR_POST2, "奇摩新聞");
fprintf(fpw, "標題: %s\n時間: %s\n", enews->title, Now());
/* html -> text */
article_begin = 0;
while (fgets(buf, sizeof(buf), fpr))
{
if (!article_begin) /* 文章開始 */
{
if (strstr(buf, "<!--end 標題寄給朋友列印-->"))
article_begin = 1;
continue;
}
/* 文章結束 */
if (strstr(buf, "<div style=\042clear:both;display:none"))
break;
if ((strS = strstr(buf, "<big>")) &&
(strE = strstr(strS + 5, "</big>"))) /* 本文部分 */
{
*strE = '\n';
*(strE + 1) = '\0';
fouts(strS + 5, fpw);
continue;
}
if ((strS = strstr(buf, "<small>")) &&
(strE = strstr(strS + 29, "</font>"))) /* 來源部分 */
{
*strE = '\n';
*(strE + 1) = '\0';
fouts(strS + 29, fpw);
}
}
/* 結尾加上連結 */
fprintf(fpw, "\n--\nYahoo!奇摩新聞\n%s\n", enews->link);
fclose(fpw);
if (!old_link(fold, enews->link))
post_board(fpath, enews->title, enews->kind);
}
fclose(fpr);
unlink(NEWS_FILE); /* 清除暫存檔 */
}
}
static void
html_fetch(fpath, kind) /* 將這檔案中有效的連結找出來 */
char *fpath;
char kind; /* 種類 */
{
static int chrono = 0;
FILE *fp;
char folder[64], fold[64], buf[1024];
char *str1, *str2, *str3;
ENEWS enews;
int article_num;
if (!(fp = fopen(fpath, "r")))
return;
sprintf(folder, "run/kimo/%c/.ENEWS", kind);
sprintf(fold, "%s.o", folder);
f_mv(folder, fold);
#if 0
處理 HTML 格式如下:
<a href="/040520/44/nwtu.html" class="title">北市兩公車對撞 13名乘客送醫<!-- 20040520 --></a>
#endif
article_num = 0;
while (fgets(buf, 1024, fp) && article_num <= 16)
{
if ((str1 = strstr(buf, "<a href=\"/")) && /* 只處理連結 */
(str2 = strstr(str1 + 10, "\" class=\"title\">")) &&
(str3 = strstr(str2 + 16, "<!-- ")))
{
*str2 = '\0';
*str3 = '\0';
/* 加入 record */
memset(&enews, 0, sizeof(ENEWS));
enews.chrono = ++chrono; /* 每篇文章一個編號 */
enews.kind = kind;
sprintf(enews.xname, "A%06d%c", chrono, kind);
sprintf(enews.link, YAHOO_URL "%s", str1 + 10);
str_ncpy(enews.title, str2 + 16, sizeof(enews.title));
if (!rec_add(folder, &enews, sizeof(ENEWS)))
html_download(&enews, fold);
article_num++;
}
}
fclose(fp);
}
/*-------------------------------------------------------*/
/* 主程式 */
/*-------------------------------------------------------*/
int
main()
{
char kind;
char cmd[256];
char *class[12] =
{
"polity", "society", "international", "twoshore",
"finance", "entertain", "sports", "leisure",
"relaxation", "health", "technology", "odd"
};
chdir(BBSHOME);
init_bshm();
/* 抓 Yahoo cookie */
system(LYNX_PATH " -dump http://tw.yahoo.com/ > " INDEX_FILE);
unlink(INDEX_FILE);
/* 抓資料並分析之 */
for (kind = 'A'; kind <= 'L'; kind++)
{
sprintf(cmd, LYNX_PATH " " YAHOO_URL "%s > " INDEX_FILE,
class[kind - 'A']);
system(cmd);
html_fetch(INDEX_FILE, kind);
unlink(INDEX_FILE); /* 清除暫存檔 */
}
return 0;
}
--
╭┼ Origin: Maple-itoc˙動力核心 processor.tfcis.org
┼╯ Author: itoc 從 pc512-2.ee.nctu.edu.tw 發表精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻