作者chwaian.bbs@cpu.tfcis.org (無言) 看板: plan
標題[功能]抓取奇摩電影
時間動力核心 (2004/11/03 Wed 00:19:17) Updated: 2006/03/08
拿itoc寫的NCTUnews.c(這隻程式真好用@_@)改的
會抓 http://tw.movie.yahoo.com/movie_comming.html 的文章
還要開 Kimo_Movies 板
: crontab -e 加入這二行
# 奇摩電影每天抓兩次
5 10,20 * * * bin/Kimomovie > /dev/null 2>&1
: src/util/Makefile
EXE = ... Kimomovie
: src/util/Kimomovie.c 新增此程式
/*-------------------------------------------------------*/
/* util/Kimomovie.c ( NTHU CS MapleBBS Ver 3.10 ) */
/*-------------------------------------------------------*/
/* target : 奇摩電影 */
/* create : 04/05/20 */
/* update : / / */
/* author : chwaian.bbs@cpu.tfcis.org */
/*-------------------------------------------------------*/
#include "bbs.h"
#define LYNX_PATH "/usr/local/bin/lynx --source" /* lynx 的絕對路徑 */
/*-------------------------------------------------------*/
/* BRD shm 部分須與 cache.c 相容 */
/*-------------------------------------------------------*/
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 char *Brdname = "Kimo_Movies"; /* 欲 post 的看板 */
static char *Userid = "奇摩電影"; /* 作者 */
static char *Username = "最新電影"; /* 暱稱 */
static void
new_post(fpath, title) /* 發文到看板 */
char *fpath; /* 檔案路徑 */
char *title; /* 文章標題 */
{
HDR hdr;
char folder[64];
brd_fpath(folder, Brdname, FN_DIR);
hdr_stamp(folder, HDR_LINK | 'A', &hdr, fpath);
strcpy(hdr.owner, Userid);
strcpy(hdr.nick, Username);
strcpy(hdr.title, title);
rec_add(folder, &hdr, sizeof(HDR));
update_btime(Brdname);
}
/*-------------------------------------------------------*/
/* 抓網頁 */
/*-------------------------------------------------------*/
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;
}
/* 跳過 \t */
if (ch == '\t')
return;
if (!in_tag)
{
if (in_chi) /* 前一個char是中文字的第一碼 */
in_chi = 0;
else if (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
strip_title(str, title)
uschar *str, *title;
{
int ch, len = 0;
uschar *dst;
/* 去掉 str 中的 \t 及最後的 <tag>,存在 title */
dst = title;
while (ch = *str++)
{
if (ch == '<')
break;
if (ch != '\t')
{
*dst++ = ch;
if (++len > TTLEN)
break;
}
}
*dst = '\0';
}
static void
html_download(actno) /* 下載文章並轉換為文字檔 */
int actno;
{
char link[128], title[TTLEN + 1], title2[TTLEN + 1];
char buf[2048]; /* 假設文章每段不會超過 2048 字 */
char *fsrc = "tmp/Kimomovie.src";
char *fdst = "tmp/Kimomovie.dst";
FILE *fpr, *fpw;
int mode;
char *ptr;
int right; /* 不存在的網址跳過 */
right = 0;
/* 下載文章 */
sprintf(link, "http://tw.movie.yahoo.com/mstory.html?t=movie&id=%d", actno);
sprintf(buf, LYNX_PATH " '%s' > %s", link, fsrc);
system(buf);
/* 轉換為文字檔 */
if (fpr = fopen(fsrc, "r"))
{
if (fpw = fopen(fdst, "w"))
{
/* 開頭加上檔頭 */
while (fgets(buf, sizeof(buf), fpr))
{
/* film_people.gif 的下一行就是標題 */
if (strstr(buf, "film_people.gif"))
{
fgets(buf, sizeof(buf), fpr);
fgets(buf, sizeof(buf), fpr);
strip_title(buf, title);
fgets(buf, sizeof(buf), fpr);
if (fgets(buf, sizeof(buf), fpr))
{
strip_title(buf, title2);
sprintf(title,"%s (%s)",title,title2);
fprintf(fpw, "%s %s (%s) %s %s\n",
STR_AUTHOR1, Userid, Username, STR_POST2, Brdname);
fprintf(fpw, "標題: %s\n時間: %s\n\n", title, Now());
right = 1;
}
break;
}
}
while (fgets(buf, sizeof(buf), fpr))
{
if (strstr(buf, "類 型:"))
{
fgets(buf, sizeof(buf), fpr);
fgets(buf, sizeof(buf), fpr);
strip_title(buf, title2);
fprintf(fpw, "\n類 型:%s\n", title2);
}
else if (strstr(buf, "片 長:"))
{
fgets(buf, sizeof(buf), fpr);
fgets(buf, sizeof(buf), fpr);
strip_title(buf, title2);
fprintf(fpw, "\n片 長:%s\n", title2);
}
else if (strstr(buf, "分 級:"))
{
fgets(buf, sizeof(buf), fpr);
fgets(buf, sizeof(buf), fpr);
strip_title(buf, title2);
fprintf(fpw, "\n分 級:%s\n", title2);
}
else if (strstr(buf, "導 演:"))
{
fgets(buf, sizeof(buf), fpr);
fgets(buf, sizeof(buf), fpr);
strip_title(buf, title2);
fprintf(fpw, "\n導 演:%s\n", title2);
}
else if (strstr(buf, "演 員:"))
{
fgets(buf, sizeof(buf), fpr);
fgets(buf, sizeof(buf), fpr);
strip_title(buf, title2);
fprintf(fpw, "\n演 員:%s\n", title2);
}
else if (strstr(buf, "發行公司:"))
{
fgets(buf, sizeof(buf), fpr);
fgets(buf, sizeof(buf), fpr);
strip_title(buf, title2);
fprintf(fpw, "\n發行公司:%s\n", title2);
}
else if (strstr(buf, "上映日期:"))
{
fgets(buf, sizeof(buf), fpr);
fgets(buf, sizeof(buf), fpr);
strip_title(buf, title2);
fprintf(fpw, "\n上映日期:%s\n", title2);
fprintf(fpw, "\n劇情簡介:\n");
break;
}
}
mode = 0; /* 0:未開始 1:印到一半 2:結束 */
while (fgets(buf, sizeof(buf), fpr))
{
if (ptr = strstr(buf, "<td class=\"mbody\">"))
{
*ptr = '\0';
mode++;
}
else if (strstr(buf, "<!--影片內容介紹開始-->"))
{
mode++;
}
if (mode)
{
fouts(buf, fpw);
if (mode == 2)
break;
}
}
/* 結尾加上來源 */
fprintf(fpw, "\n--\nYahoo!奇摩電影\n%s\n", link);
fclose(fpw);
fclose(fpr);
if (right)
new_post(fdst, title);
unlink(fdst);
}
unlink(fsrc);
}
}
/*-------------------------------------------------------*/
/* 主程式 */
/*-------------------------------------------------------*/
static int
urhigh_query()
{
char *ftmp = "tmp/Kimomovie.tmp";
char buf[512]; /* 假設每行不會超過 512 字 */
char *ptr;
FILE *fp;
int high;
int tmp;
high = 0;
tmp = 0;
sprintf(buf, LYNX_PATH " http://tw.movie.yahoo.com/movie_comming.html > %s",
ftmp);
system(buf);
if (fp = fopen(ftmp, "r"))
{
while (fgets(buf, sizeof(buf), fp))
{
if (ptr = strstr(buf, "mstory.html?t=movie&id="))
{
tmp = atoi(ptr + 23);
if(tmp > high)
high = tmp;
}
}
fclose(fp);
unlink(ftmp);
}
return high;
}
int
main()
{
FILE *fp;
int myhigh, urhigh;
char buf[10];
chdir(BBSHOME);
/* 看自己抓到第幾篇了 */
myhigh = 0;
if (fp = fopen("run/Kimomovie", "r"))
{
fscanf(fp, "%8s", buf);
fclose(fp);
if ((urhigh = atoi(buf)) > 0)
myhigh = urhigh;
}
/* 看奇摩電影最新的有幾篇 */
urhigh = urhigh_query();
if (!myhigh) /* 如果自己沒有篇數計數器,那就抓最後三篇 */
myhigh = urhigh - 3;
if (myhigh >= urhigh) /* 沒有新文章 */
return 0;
init_bshm();
/* 去抓新的文章 */
for (myhigh++; myhigh <= urhigh; myhigh++)
html_download(myhigh);
/* 更新自己的篇數計數器 */
if (fp = fopen("run/Kimomovie", "w"))
{
fprintf(fp, "%d", urhigh);
fclose(fp);
}
return 0;
}
--
◤◥ Origin: Maple-itoc˙動力核心 cpu.tfcis.org
◣◢ Author: chwaian 從 61-216-216-43.dynamic.hinet.net 發表