dms-scrape 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +13 -14
  2. package/extractfrombrowser.js +12 -0
  3. package/index.mjs +38 -5
  4. package/lib/array2String.mjs +5 -0
  5. package/lib/determineCategory.mjs +5 -5
  6. package/lib/filterContent.mjs +31 -42
  7. package/lib/processHTML.mjs +39 -71
  8. package/lib/sources.mjs +52 -0
  9. package/package.json +1 -1
  10. package/sources/T1/CTEE.mjs +32 -18
  11. package/sources/T1/DIGITIMES.mjs +18 -4
  12. package/sources/T1/UDNMoney.mjs +3 -3
  13. package/sources/T2/CHINATIMES.mjs +36 -17
  14. package/sources/T2/NXTAPPLE.mjs +30 -0
  15. package/sources/T3/SETN.mjs +35 -0
  16. package/sources/T5/CNYES.mjs +25 -0
  17. package/sources/T5/COMPOTECHASIA.mjs +30 -0
  18. package/sources/T5/INSIDE.mjs +15 -0
  19. package/sources/T5/SAYDIGI.mjs +22 -0
  20. package/sources/T5/TECHBANG.mjs +20 -0
  21. package/sources/T5/TECHORANGE.mjs +23 -21
  22. package/test/cnyestest.js +814 -0
  23. package/test/compotechtest.js +561 -0
  24. package/test/insidetest.js +1399 -0
  25. package/test/saydigitest.js +1000 -0
  26. package/test/techbangtest.js +1109 -0
  27. package/test/techrangetest.js +3101 -0
  28. package/test/tested/chinatest.js +4761 -0
  29. package/test/tested/cteetest.js +1406 -0
  30. package/test/tested/digitest.html +1789 -0
  31. package/test/tested/digitimes2.js +2218 -0
  32. package/test/tested/nextapple.js +1546 -0
  33. package/test/tested/setntest.js +2728 -0
  34. package/test.mjs +62 -13
  35. package/sources/T1/digitimes.html +0 -2598
  36. package/sources/T1/digitimes2.html +0 -2567
  37. package/sources/T5/TECHBANG(unfinished).mjs +0 -13
  38. /package/{sources/T1 → test/tested}/digitimes3.html +0 -0
  39. /package/{sources/T1 → test/tested}/digitimes4.html +0 -0
package/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## Currently supported sources
4
4
  ### T1
5
- - [ ] 電子時報*
6
- - [ ] 工商時報*
5
+ - [x] 電子時報 HTML ONLY
6
+ - [x] 工商時報 HTML ONLY
7
7
  - [x] 經濟日報 (UDNMoney)
8
8
 
9
9
  ### T2
@@ -11,13 +11,13 @@
11
11
  - [x] 自由時報
12
12
  - [x] 聯合報
13
13
  - [ ] 聯合晚報
14
- - [ ] 中國時報*
15
- - [ ] 時報資訊
14
+ - [x] 中國時報 HTML ONLY
15
+ - [x] 時報資訊 HTML ONLY
16
16
  - [ ] 商業週刊
17
- - [ ] 壹蘋新聞網
17
+ - [x] 壹蘋新聞網
18
18
 
19
19
  ### T3 電視台
20
- - [ ] 三立
20
+ - [x] 三立
21
21
  - [ ] 華視
22
22
  - [ ] 三立新聞台
23
23
  - [ ] 東森新聞
@@ -28,7 +28,7 @@
28
28
  ### T4
29
29
  - [x] 中央社
30
30
  - [x] 太報
31
- - [x] ETDAY ETtoday
31
+ - [x] ETtoday (ETDAY)
32
32
  - [ ] cw
33
33
 
34
34
  ### T5
@@ -36,16 +36,15 @@
36
36
  - [x] Cool3c
37
37
  - [x] ePrice
38
38
  - [x] Sogi 手機王
39
- - [ ] TechOrange*
39
+ - [x] TechOrange HTML ONLY
40
40
  - [x] KOCPC 電腦王阿達
41
41
  - [x] TechNews 科技新報
42
- - [ ] TechBang T客邦
42
+ - [x] TechBang T客邦
43
43
  - [x] XFastest minor bug
44
- - [ ] 鉅亨網
45
- - [ ] 聯合新聞網?
46
- - [ ] 點子生活
47
- - [ ] 智慧電子解決方案設計平台
48
- - [ ] Inside
44
+ - [x] 鉅亨網
45
+ - [x] 點子生活
46
+ - [x] 智慧電子解決方案設計平台
47
+ - [x] Inside
49
48
  - [ ] Engadget
50
49
  - [ ] 電獺少女
51
50
  - [ ] CTIMES
@@ -0,0 +1,12 @@
1
+ var fullHTML = document.documentElement.outerHTML;
2
+
3
+ // Create a temporary DOM element to manipulate the HTML
4
+ var tempDiv = document.createElement('div');
5
+ tempDiv.innerHTML = fullHTML;
6
+
7
+ // Remove all <script> and <style> tags
8
+ var scriptsAndStyles = tempDiv.querySelectorAll('script, style, link');
9
+ scriptsAndStyles.forEach(tag => tag.remove());
10
+
11
+ // Print the HTML without the <script> and <style> tags
12
+ console.log(tempDiv.innerHTML);
package/index.mjs CHANGED
@@ -1,8 +1,41 @@
1
1
  import { processHTML } from "./lib/processHTML.mjs";
2
+ import { v4 as uuid } from "uuid";
3
+ import * as cheerio from 'cheerio'
4
+ function checkLink(link) {
5
+ const linksNeedText = ["digitimes", "ctee", "chinatimes", "techorange"];
6
+ for (const l of linksNeedText) {
7
+ if (link.includes(l)) {
8
+ return true;
9
+ } else {
10
+ return false;
11
+ }
12
+ }
13
+ }
2
14
  export async function dmsScrape(type, link, html) {
3
- return type == "link"
4
- ? processHTML(link, await (await fetch(link)).text())
5
- : type == "html"
6
- ? processHTML(link, html)
7
- : { error: "Must specify type", url: link };
15
+ var data;
16
+ if (type == "link" && checkLink(link) === false) {
17
+ let $ = cheerio.load(await (await fetch(link)).text());
18
+ $("script, style, link").remove();
19
+ $("*").each(function () {
20
+ let content = $(this).html();
21
+ content = content.replace(/\$\{/g, "");
22
+ $(this).html(content);
23
+ });
24
+ let cleanedHTML = $.html();
25
+ data = processHTML(link, cleanedHTML);
26
+ } else if (type == "link" && checkLink(link) === true) {
27
+ data = {
28
+ error: "Needs extension",
29
+ url: link,
30
+ id: uuid(),
31
+ };
32
+ } else if (type == "html") {
33
+ data = processHTML(link, html);
34
+ } else {
35
+ data = {
36
+ error: "Must specify type",
37
+ url: link,
38
+ };
39
+ }
40
+ return data;
8
41
  }
@@ -0,0 +1,5 @@
1
+ export function array2String(data) {
2
+ Array.isArray(data)
3
+ ? data.toString()
4
+ : data;
5
+ }
@@ -1,18 +1,18 @@
1
1
  export function determineCategory(title) {
2
2
  switch (true) {
3
3
  case title.includes("高通"):
4
- return "Qualcomm相關新聞";
4
+ return "qualcomm";
5
5
 
6
6
  case title.includes("聯發科"):
7
- return "MediaTek相關新聞";
7
+ return "mediatek";
8
8
 
9
9
  case title.includes("5G"):
10
- return "無線通訊市場";
10
+ return "commu";
11
11
 
12
12
  case title.includes("OPPO") || title.includes("PC"):
13
- return "智慧型手機/消費性電子產品";
13
+ return "phone";
14
14
 
15
15
  default:
16
- return "其他業界重要訊息";
16
+ return "other";
17
17
  }
18
18
  }
@@ -1,45 +1,34 @@
1
1
  export function filterContent(inputArray) {
2
- inputArray = inputArray.map((line) => line.trim());
2
+ const excludedStartWords = [
3
+ "一手掌握經濟脈動", "《你可能還想看》", "(", "不用抽", "記者", "▲", "<", "\\", "。",
4
+ "此處", "還在靠社群媒體", "訂閱即同意", "*本文開放", "(本文訊息", "相關資源", "• 更多關於:", "快加入 INSIDE"
5
+ ];
3
6
 
4
- inputArray = inputArray.filter(
5
- (item) =>
6
- item !== "" &&
7
- !item.startsWith("一手掌握經濟脈動") &&
8
- item !== "《你可能還想看》" &&
9
- !item.includes("請繼續往下閱讀...") &&
10
- !item.startsWith("(") &&
11
- !item.startsWith("不用抽") &&
12
- !item.includes("核稿編輯") &&
13
- !item.startsWith("記者") &&
14
- !item.includes("圖/") &&
15
- !item.startsWith("▲") &&
16
- !item.startsWith("<") &&
17
- !item.includes("引用來源:") &&
18
- !item.startsWith("\\") &&
19
- !item.includes("<h2>") &&
20
- !item.includes("&nbsp;") &&
21
- !item.endsWith("") &&
22
- !item.includes("訂閱手機王") &&
23
- !item.includes("想快速知道") &&
24
- !item.includes("資料來源:") &&
25
- !item.includes("&nbsp;") &&
26
- !item.includes("上傳") &&
27
- !item.includes("消息來源") &&
28
- !item.includes(".jpg") &&
29
- !item.startsWith("(") &&
30
- !item.includes("下載附件") &&
31
- !item.includes("保存到相冊") &&
32
- !item.includes(".png") &&
33
- !item.includes(",請點選") &&
34
- !item.includes(",請造訪") &&
35
- !item.startsWith("。") &&
36
- !item.includes("其他因素不同而產生差異") &&
37
- !item.startsWith("此處") &&
38
- !item.length <= 2 &&
39
- !item.includes("中央社「一手新聞」 app") &&
40
- !item.includes("本網站之文字、圖片及影音")
41
- );
42
- inputArray = inputArray.map((str) => str.replace(/<\/?[^>]+(>|$)/g, ""));
43
- inputArray = inputArray.map((line) => line.trim());
44
- return inputArray;
7
+ const excludedSubstrings = [
8
+ "請繼續往下閱讀...", "核稿編輯", "圖/", "引用來源:", "<h2>", "&nbsp;", "訂閱手機王",
9
+ "想快速知道", "資料來源:", "上傳", "消息來源", ".jpg", "下載附件", "保存到相冊", ".png",
10
+ ",請點選", ",請造訪", "其他因素不同而產生差異", "中央社「一手新聞」 app",
11
+ "本網站之文字、圖片及影音", "#content>a:hover {", "color: ", "text-decoration: "
12
+ ];
13
+
14
+ const excludedEndsWith = [""];
15
+
16
+ // Combined regex for general replacements
17
+ const regex = /<\/?[^>]+(>|$)|\s+/g;
18
+
19
+ return inputArray
20
+ .map((str) => str.replace(regex, " ").trim()) // Clean HTML and trim spaces
21
+ .filter((item) => {
22
+ // Filter based on start, substring, and length
23
+ if (
24
+ item === "" ||
25
+ excludedStartWords.some((word) => item.startsWith(word)) ||
26
+ excludedSubstrings.some((substring) => item.includes(substring)) ||
27
+ excludedEndsWith.some((end) => item.endsWith(end)) ||
28
+ item.length <= 2
29
+ ) {
30
+ return false;
31
+ }
32
+ return true;
33
+ });
45
34
  }
@@ -1,83 +1,51 @@
1
- import { LTN3C } from "../sources/T2/LTN3C.mjs";
2
- import { LTNEC } from "../sources/T2/LTNEC.mjs";
3
- import { UDN } from "../sources/T2/UDN.mjs";
4
- import { UDNMoney } from "../sources/T1/UDNMoney.mjs";
5
- import { ETDAY } from "../sources/T4/ETDAY.mjs";
6
- import { EPRICE } from "../sources/T5/EPRICE.mjs";
7
- import { COOL3C } from "../sources/T5/COOL3C.mjs";
8
- import { MASHDIGI } from "../sources/T5/MASHDIGI.mjs";
9
- import { SOGI } from "../sources/T5/SOGI.mjs";
10
1
  import * as cheerio from "cheerio";
11
- import { TECHORANGE } from "../sources/T5/TECHORANGE.mjs";
12
- import { DIGITIMES } from "../sources/T1/DIGITIMES.mjs";
13
- import { KOCPC } from "../sources/T5/KOCPC.mjs";
14
- import { XF } from "../sources/T5/XF.mjs";
15
- import { TAISOUNDS } from "../sources/T4/TAISOUNDS.mjs";
16
- import { TECHNEWS } from "../sources/T5/TECHNEWS.mjs";
17
- import { CNA } from "../sources/T4/CNA.mjs";
18
- import { v4 as uuid } from "uuid";
2
+
19
3
  import { filterContent } from "./filterContent.mjs";
20
4
  import { determineCategory } from "./determineCategory.mjs";
5
+ import { sources } from "./sources.mjs";
6
+
21
7
  function determineSource(link) {
22
- if (link.includes("3c.ltn")) {
23
- return LTN3C;
24
- } else if (link.includes("ec.ltn")) {
25
- return LTNEC;
26
- } else if (link.includes("money.udn")) {
27
- return UDNMoney;
28
- } else if (link.includes("udn")) {
29
- return UDN;
30
- } else if (link.includes("ettoday")) {
31
- return ETDAY;
32
- } else if (link.includes("eprice")) {
33
- return EPRICE;
34
- } else if (link.includes("cool3c")) {
35
- return COOL3C;
36
- } else if (link.includes("mashdigi")) {
37
- return MASHDIGI;
38
- } else if (link.includes("sogi")) {
39
- return SOGI;
40
- } else if (link.includes("techorange")) {
41
- return TECHORANGE;
42
- } else if (link.includes("digitimes")) {
43
- return DIGITIMES;
44
- } else if (link.includes("kocpc")) {
45
- return KOCPC;
46
- } else if (link.includes("xfastest")) {
47
- return XF;
48
- } else if (link.includes("taisounds")) {
49
- return TAISOUNDS;
50
- } else if (link.includes("technews")) {
51
- return TECHNEWS;
52
- } else if (link.includes("cna")) {
53
- return CNA;
54
- } else {
55
- return "unsupported";
8
+ for (const [key, value] of Object.entries(sources)) {
9
+ if (link.includes(key)) {
10
+ return value;
11
+ }
56
12
  }
13
+ return "unsupported";
57
14
  }
58
15
 
59
16
  export function processHTML(link, html) {
60
17
  const handlerFunction = determineSource(link);
61
18
  let scrapedContent;
62
- handlerFunction != "unsupported"
63
- ? ((scrapedContent = handlerFunction(cheerio.load(html))),
64
- (scrapedContent["content"] = scrapedContent["content"]
65
- ? filterContent(scrapedContent["content"]).join("\n\n")
66
- : scrapedContent["content"]),
67
- (scrapedContent["author"] = Array.isArray(scrapedContent["author"])
68
- ? scrapedContent["author"].toString()
69
- : scrapedContent["author"]),
70
- (scrapedContent["date"] = Array.isArray(scrapedContent["date"])
71
- ? scrapedContent["date"].toString()
72
- : scrapedContent["date"]),
73
- (scrapedContent["category"] = determineCategory(scrapedContent["title"])),
74
- (scrapedContent["url"] = link),
75
- (scrapedContent["content"] = scrapedContent["content"]))
76
- : (scrapedContent = {
77
- error: handlerFunction,
78
- url: link,
79
- });
19
+ if (handlerFunction != "unsupported") {
20
+ scrapedContent = handlerFunction(cheerio.load(html));
21
+
22
+ if (scrapedContent["content"]) {
23
+ scrapedContent["content"] = filterContent(scrapedContent["content"]).join(
24
+ "\n\n"
25
+ );
26
+ }
27
+
28
+ if (Array.isArray(scrapedContent["author"])) {
29
+ scrapedContent["author"] = scrapedContent["author"].toString();
30
+ }
31
+ if (Array.isArray(scrapedContent["date"])) {
32
+ scrapedContent["date"] = scrapedContent["date"].toString();
33
+ }
34
+
35
+ if (Array.isArray(scrapedContent["title"])) {
36
+ scrapedContent["title"] = scrapedContent["title"].toString();
37
+ }
38
+
39
+ scrapedContent["category"] = determineCategory(scrapedContent["title"]);
40
+ scrapedContent["url"] = link;
41
+ } else {
42
+ scrapedContent = {
43
+ error: handlerFunction,
44
+ url: link,
45
+ category: "other",
46
+ };
47
+ }
48
+
80
49
 
81
- scrapedContent["id"] = uuid();
82
- return scrapedContent
50
+ return scrapedContent;
83
51
  }
@@ -0,0 +1,52 @@
1
+ import { LTN3C } from "../sources/T2/LTN3C.mjs";
2
+ import { LTNEC } from "../sources/T2/LTNEC.mjs";
3
+ import { UDN } from "../sources/T2/UDN.mjs";
4
+ import { UDNMoney } from "../sources/T1/UDNMoney.mjs";
5
+ import { ETDAY } from "../sources/T4/ETDAY.mjs";
6
+ import { EPRICE } from "../sources/T5/EPRICE.mjs";
7
+ import { COOL3C } from "../sources/T5/COOL3C.mjs";
8
+ import { MASHDIGI } from "../sources/T5/MASHDIGI.mjs";
9
+ import { SOGI } from "../sources/T5/SOGI.mjs";
10
+ import { TECHORANGE } from "../sources/T5/TECHORANGE.mjs";
11
+ import { DIGITIMES } from "../sources/T1/DIGITIMES.mjs";
12
+ import { KOCPC } from "../sources/T5/KOCPC.mjs";
13
+ import { XF } from "../sources/T5/XF.mjs";
14
+ import { TAISOUNDS } from "../sources/T4/TAISOUNDS.mjs";
15
+ import { TECHNEWS } from "../sources/T5/TECHNEWS.mjs";
16
+ import { CNA } from "../sources/T4/CNA.mjs";
17
+ import { CTEE } from "../sources/T1/CTEE.mjs";
18
+ import { CHINATIMES } from "../sources/T2/CHINATIMES.mjs";
19
+ import { NXTAPPLE } from "../sources/T2/NXTAPPLE.mjs";
20
+ import { SETN } from "../sources/T3/SETN.mjs";
21
+ import { TECHBANG } from "../sources/T5/TECHBANG.mjs";
22
+ import { CNYES } from "../sources/T5/CNYES.mjs";
23
+ import { SAYDIGI } from "../sources/T5/SAYDIGI.mjs";
24
+ import { COMPOTECHASIA } from "../sources/T5/COMPOTECHASIA.mjs";
25
+ import { INSIDE } from "../sources/T5/INSIDE.mjs";
26
+ export const sources = {
27
+ "3c.ltn": LTN3C,
28
+ "ec.ltn": LTNEC,
29
+ "money.udn": UDNMoney,
30
+ "udn": UDN,
31
+ "ettoday": ETDAY,
32
+ "eprice": EPRICE,
33
+ "cool3c": COOL3C,
34
+ "mashdigi": MASHDIGI,
35
+ "sogi": SOGI,
36
+ "techorange": TECHORANGE,
37
+ "digitimes": DIGITIMES,
38
+ "kocpc": KOCPC,
39
+ "xfastest": XF,
40
+ "taisounds": TAISOUNDS,
41
+ "technews": TECHNEWS,
42
+ "cna": CNA,
43
+ "ctee": CTEE,
44
+ "chinatimes": CHINATIMES,
45
+ "nextapple": NXTAPPLE,
46
+ "setn": SETN,
47
+ "techbang": TECHBANG,
48
+ "cnyes": CNYES,
49
+ "saydigi": SAYDIGI,
50
+ "compotechasia": COMPOTECHASIA,
51
+ "inside": INSIDE
52
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dms-scrape",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "main": "index.mjs",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -1,18 +1,32 @@
1
- ///////ctee 、綜合外電
2
- // https://www.ctee.com.tw/news/20240821700211-439901
3
- // https://www.ctee.com.tw/news/20240821701357-430704
4
- // case link.includes("ctee"):
5
- // title = $("h1.main-title").text().trim();
6
- // date_source_author = `${$("li.publish-date time")
7
- // .text()
8
- // .replace(/\./g, "-")} / 工商時報 / ${$("span.name").text().trim()}`;
9
- // content = [];
10
- // // content?.push($('blockquote p').text())
11
- // $("article p").each((i, element) => {
12
- // const text = $(element).text().trim();
13
- // if (text) {
14
- // content?.push(text);
15
- // }
16
- // });
17
- // break;
18
- //////
1
+ export function CTEE($) {
2
+ const data = $.extract({
3
+ title: [{ selector: "h1.main-title", value: (el) => $(el).text().trim() }],
4
+ date: [
5
+ {
6
+ selector: "li.publish-date time",
7
+ value: (el, key) => {
8
+ const data = $(el).text().replace(/\./g, "-");
9
+ return data;
10
+ },
11
+ },
12
+ ],
13
+ author: [
14
+ {
15
+ selector: "span.name",
16
+ value: (el) => $(el).text().trim()
17
+ }],
18
+ content: [
19
+ {
20
+ selector: "article p",
21
+ value: (el, key) => {
22
+ // const sampleKey = this.findIndex(item => item.includes("延伸閱讀"))
23
+ if ($(el).text().trim()) {
24
+ return $(el).text().trim();
25
+ }
26
+ },
27
+ },
28
+ ],
29
+ });
30
+ data["source"] = "工商時報";
31
+ return data;
32
+ }
@@ -1,9 +1,23 @@
1
+
2
+
1
3
  export function DIGITIMES($) {
2
- let data = {};
3
- data["title"] = $("h1.news-title").text();
4
- data["date"] = $("time").text();
4
+ const data = $.extract({
5
+ title: "h1.news-title",
6
+ date: [{selector: "time", value: (el) => $(el).text().replace(/(\d{4})\/(\d{2})\/(\d{2}) .*/, '$1-$2-$3')}],
7
+
8
+ content: [
9
+ {
10
+ selector: "div#newsText.Article.clearfix.txt-20 > p",
11
+ value: (el, key) => {
12
+ // const sampleKey = this.findIndex(item => item.includes("延伸閱讀"))
13
+ if ($(el).text().trim().replace(/\t/g, '') != '') {
14
+ return $(el).text().trim().replace(/\t/g, '').trim();
15
+ }
16
+ },
17
+ },
18
+ ],
19
+ });
5
20
  data["source"] = "電子時報";
6
21
  data["author"] = $("font").first().text();
7
- data["content"] = [];
8
22
  return data;
9
23
  }
@@ -23,16 +23,16 @@ export function UDNMoney($) {
23
23
  {
24
24
  selector: "section.article-body__editor p",
25
25
  value: (el, key) => {
26
- const sampleKey = this.findIndex(item => item.includes("延伸閱讀"))
26
+ // const sampleKey = this.findIndex(item => item.includes("延伸閱讀"))
27
27
  if (!$(el).text().trim() == "") {
28
28
  const sample = $(el)
29
29
  .text()
30
30
  .replace(/\$\(.*/s, "")
31
31
  .trim();
32
32
 
33
- if (key < sampleKey) {
33
+ // if (key < sampleKey) {
34
34
  return sample;
35
- }
35
+ // }
36
36
 
37
37
  }
38
38
  },
@@ -1,19 +1,38 @@
1
1
  /////chinatimes bug time wrong
2
- // https://www.chinatimes.com/realtimenews/20240820002976-260412?chdtv
3
- // case link.includes("chinatimes"):
4
- // title = $("h1.article-title").text();
5
- // date_source_author =
6
- // $("span.date").first().text() +
7
- // " / " +
8
- // $("div.source").text() +
9
- // " / " +
10
- // $("div.author").text();
2
+ // https://www.chinatimes.com/realtimenews/20240820002976-260412?chdtv
3
+ // case link.includes("chinatimes"):
4
+ // title = $("h1.article-title").text();
5
+ // date_source_author =
6
+ // $("span.date").first().text() +
7
+ // " / " +
8
+ // $("div.source").text() +
9
+ // " / " +
10
+ // $("div.author").text();
11
11
 
12
- // content = [];
13
- // $("div.article-body p").each((index, element) => {
14
- // if (!$(element).text().trim() == "") {
15
- // content.push($(element).text().trim());
16
- // }
17
- // });
18
- // break;
19
- //////
12
+ // content = [];
13
+ // $("div.article-body p").each((index, element) => {
14
+ // if (!$(element).text().trim() == "") {
15
+ // content.push($(element).text().trim());
16
+ // }
17
+ // });
18
+ // break;
19
+ //////
20
+ export function CHINATIMES($) {
21
+ const data = $.extract({
22
+ title: "h1.article-title",
23
+ date: [{ selector: "span.date", value: (el) => $(el).text().replace(/\//g, "-") }],
24
+ source: "div.source",
25
+ author: "div.author",
26
+ content: [
27
+ {
28
+ selector: "div.article-body p",
29
+ value: (el) => {
30
+ if ($(el).text().trim() !== "") {
31
+ return $(el).text().trim();
32
+ }
33
+ },
34
+ },
35
+ ],
36
+ });
37
+ return data;
38
+ }
@@ -0,0 +1,30 @@
1
+ export function NXTAPPLE($) {
2
+ const data = $.extract({
3
+ title: "title",
4
+
5
+ date: [
6
+ {
7
+ selector: "time:first",
8
+ value: (el) => $(el).attr("datetime").split("T")[0],
9
+ },
10
+ ],
11
+ author: [
12
+ {
13
+ selector: "a[href^='https://tw.nextapple.com/search/author/']",
14
+ value: (el) => $(el).text().trim(),
15
+ },
16
+ ],
17
+ content: [
18
+ {
19
+ selector: "div.post-content > p",
20
+ value: (el) => {
21
+ if ($(el).text().trim() !== "") {
22
+ return $(el).text().trim();
23
+ }
24
+ },
25
+ },
26
+ ],
27
+ });
28
+ data["source"] = "壹蘋新聞網"
29
+ return data;
30
+ }
@@ -0,0 +1,35 @@
1
+ export function SETN($) {
2
+ const data = $.extract({
3
+ title: [{selector: "title", value: (el) => $(el).text().trim()}],
4
+
5
+ date: [
6
+ {
7
+ selector: "meta[name=lastmod]",
8
+ value: (el) => $(el).attr("content").split("T")[0],
9
+ },
10
+ ],
11
+ author: [
12
+ {
13
+ selector: "div p:not([style]):first",
14
+ value: (el) =>
15
+ $(el)
16
+ .text()
17
+ .match(/(?<=記者).{3}/)
18
+ ? $(el)
19
+ .text()
20
+ .match(/(?<=記者).{3}/)[0]
21
+ .trim()
22
+ : $(el).text(),
23
+ },
24
+ ],
25
+ });
26
+ data["source"] = "三立新聞網";
27
+ data["content"] = [];
28
+
29
+ $("div p:not([style])")
30
+ .slice(1)
31
+ .each(function () {
32
+ data["content"].push($(this).text());
33
+ });
34
+ return data;
35
+ }