dms-scrape 0.4.4 → 0.4.6

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 (51) hide show
  1. package/dist/index.js +70 -0
  2. package/package.json +9 -5
  3. package/.gitattributes +0 -2
  4. package/.vscode/launch.json +0 -18
  5. package/dms-scrape.d.ts +0 -1
  6. package/extractfrombrowser.js +0 -12
  7. package/index.mjs +0 -50
  8. package/lib/array2String.mjs +0 -5
  9. package/lib/determineCategory.mjs +0 -18
  10. package/lib/filterContent.mjs +0 -34
  11. package/lib/processHTML.mjs +0 -50
  12. package/lib/sources.mjs +0 -52
  13. package/sources/T1/CTEE.mjs +0 -32
  14. package/sources/T1/DIGITIMES.mjs +0 -23
  15. package/sources/T1/UDNMoney.mjs +0 -46
  16. package/sources/T2/CHINATIMES.mjs +0 -43
  17. package/sources/T2/LTN3C.mjs +0 -34
  18. package/sources/T2/LTNEC.mjs +0 -40
  19. package/sources/T2/NXTAPPLE.mjs +0 -30
  20. package/sources/T2/UDN.mjs +0 -26
  21. package/sources/T3/SETN.mjs +0 -35
  22. package/sources/T4/CNA.mjs +0 -33
  23. package/sources/T4/ETDAY.mjs +0 -39
  24. package/sources/T4/TAISOUNDS.mjs +0 -21
  25. package/sources/T5/CNYES.mjs +0 -25
  26. package/sources/T5/COMPOTECHASIA.mjs +0 -30
  27. package/sources/T5/COOL3C.mjs +0 -26
  28. package/sources/T5/EPRICE.mjs +0 -19
  29. package/sources/T5/INSIDE.mjs +0 -15
  30. package/sources/T5/KOCPC.mjs +0 -28
  31. package/sources/T5/MASHDIGI.mjs +0 -27
  32. package/sources/T5/SAYDIGI.mjs +0 -22
  33. package/sources/T5/SOGI.mjs +0 -46
  34. package/sources/T5/TECHBANG.mjs +0 -20
  35. package/sources/T5/TECHNEWS.mjs +0 -17
  36. package/sources/T5/TECHORANGE.mjs +0 -26
  37. package/sources/T5/XF.mjs +0 -28
  38. package/test/cnyestest.js +0 -814
  39. package/test/compotechtest.js +0 -561
  40. package/test/insidetest.js +0 -1399
  41. package/test/saydigitest.js +0 -1000
  42. package/test/techbangtest.js +0 -1109
  43. package/test/techrangetest.js +0 -3101
  44. package/test/tested/chinatest.js +0 -4761
  45. package/test/tested/cteetest.js +0 -1406
  46. package/test/tested/digitest.js +0 -1664
  47. package/test/tested/digitimes3.html +0 -2598
  48. package/test/tested/digitimes4.html +0 -2614
  49. package/test/tested/nextapple.js +0 -1546
  50. package/test/tested/setntest.js +0 -2728
  51. package/test.mjs +0 -108
package/package.json CHANGED
@@ -1,14 +1,18 @@
1
1
  {
2
2
  "name": "dms-scrape",
3
- "version": "0.4.4",
4
- "main": "index.mjs",
3
+ "version": "0.4.6",
4
+ "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
7
- "test": "node test.mjs"
7
+ "test": "node test.mjs",
8
+ "build": "node build.mjs"
8
9
  },
9
- "author": "",
10
+ "files": [
11
+ "dist/*"
12
+ ],
13
+ "author": "lostmypillow",
10
14
  "license": "ISC",
11
- "description": "",
15
+ "description": "Scraper for CompassPR DMS Scraper",
12
16
  "devDependencies": {
13
17
  "esbuild": "^0.23.1"
14
18
  },
package/.gitattributes DELETED
@@ -1,2 +0,0 @@
1
- # Auto detect text files and perform LF normalization
2
- * text=auto
@@ -1,18 +0,0 @@
1
- {
2
- // Use IntelliSense to learn about possible attributes.
3
- // Hover to view descriptions of existing attributes.
4
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
- "version": "0.2.0",
6
- "configurations": [
7
- {
8
- "type": "node",
9
- "request": "launch",
10
- "name": "Launch Program",
11
- "console": "integratedTerminal",
12
- "skipFiles": [
13
- "<node_internals>/**"
14
- ],
15
- "program": "${workspaceFolder}\\test.mjs"
16
- }
17
- ]
18
- }
package/dms-scrape.d.ts DELETED
@@ -1 +0,0 @@
1
- declare module 'dms-scrape'
@@ -1,12 +0,0 @@
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, g, noscript, svg, img, symbol, figure, figcaption, ins');
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 DELETED
@@ -1,50 +0,0 @@
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
- let resp;
6
- const linksNeedText = [
7
- "https://www.digitimes",
8
- "https://www.ctee",
9
- "https://www.chinatimes",
10
- "https://buzzorange.com/techorange",
11
- ];
12
- for (const l of linksNeedText) {
13
- if (link.startsWith(l)) {
14
- resp = true;
15
- break;
16
- } else {
17
- resp = false;
18
- }
19
- }
20
- return resp;
21
- }
22
- export async function dmsScrape(type, link, html) {
23
- var data;
24
- if (type == "link" && checkLink(link) === false) {
25
- let $ = cheerio.load(await (await fetch(link)).text());
26
- $("script, style, link").remove();
27
- $("*").each(function () {
28
- let content = $(this).html();
29
- content = content.replace(/\$\{/g, "");
30
- $(this).html(content);
31
- });
32
- let cleanedHTML = $.html();
33
- data = processHTML(link, cleanedHTML);
34
- } else if (type == "link" && checkLink(link) === true) {
35
- data = {
36
- error: "Needs extension",
37
- url: link,
38
- id: uuid(),
39
- category: "other"
40
- };
41
- } else if (type == "html") {
42
- data = processHTML(link, html);
43
- } else {
44
- data = {
45
- error: "Must specify type",
46
- url: link,
47
- };
48
- }
49
- return data;
50
- }
@@ -1,5 +0,0 @@
1
- export function array2String(data) {
2
- Array.isArray(data)
3
- ? data.toString()
4
- : data;
5
- }
@@ -1,18 +0,0 @@
1
- export function determineCategory(title) {
2
- switch (true) {
3
- case title?.includes("高通"):
4
- return "qualcomm";
5
-
6
- case title?.includes("聯發科"):
7
- return "mediatek";
8
-
9
- case title?.includes("5G"):
10
- return "commu";
11
-
12
- case title?.includes("OPPO") || title?.includes("PC"):
13
- return "phone";
14
-
15
- default:
16
- return "other";
17
- }
18
- }
@@ -1,34 +0,0 @@
1
- export function filterContent(inputArray) {
2
- const excludedStartWords = [
3
- "一手掌握經濟脈動", "《你可能還想看》", "(", "不用抽", "記者", "▲", "<", "\\", "。",
4
- "此處", "還在靠社群媒體", "訂閱即同意", "*本文開放", "(本文訊息", "相關資源", "• 更多關於:", "快加入 INSIDE"
5
- ];
6
-
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
- });
34
- }
@@ -1,50 +0,0 @@
1
- import * as cheerio from "cheerio";
2
-
3
- import { filterContent } from "./filterContent.mjs";
4
- import { determineCategory } from "./determineCategory.mjs";
5
- import { sources } from "./sources.mjs";
6
-
7
- function determineSource(link) {
8
- for (const [key, value] of Object.entries(sources)) {
9
- if (link.includes(key)) {
10
- return value;
11
- }
12
- }
13
- return "unsupported";
14
- }
15
-
16
- export function processHTML(link, html) {
17
- const handlerFunction = determineSource(link);
18
- let scrapedContent;
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
- };
46
- }
47
-
48
-
49
- return scrapedContent;
50
- }
package/lib/sources.mjs DELETED
@@ -1,52 +0,0 @@
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
- };
@@ -1,32 +0,0 @@
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,23 +0,0 @@
1
-
2
-
3
- export function DIGITIMES($) {
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
- });
20
- data["source"] = "電子時報";
21
- data["author"] = $("font").first().text();
22
- return data;
23
- }
@@ -1,46 +0,0 @@
1
- export function UDNMoney($) {
2
- const data = $.extract({
3
- title: "h1#story_art_title",
4
- date: [
5
- {
6
- selector: "time.article-body__time",
7
- value: (el, key) => {
8
- const data = $(el).text().replace(/\//g, "-").slice(0, 10);
9
- return data;
10
- },
11
- },
12
- ],
13
- author: [
14
- {
15
- selector: "div.article-body__info > span",
16
- value: (el, key) => {
17
- const text = $(el).text();
18
- return text.replace(/.*記者(.{3}).*/, "$1");
19
- },
20
- },
21
- ],
22
- content: [
23
- {
24
- selector: "section.article-body__editor p",
25
- value: (el, key) => {
26
- // const sampleKey = this.findIndex(item => item.includes("延伸閱讀"))
27
- if (!$(el).text().trim() == "") {
28
- const sample = $(el)
29
- .text()
30
- .replace(/\$\(.*/s, "")
31
- .trim();
32
-
33
- // if (key < sampleKey) {
34
- return sample;
35
- // }
36
-
37
- }
38
- },
39
- },
40
- ],
41
- });
42
- data["source"] = "經濟日報";
43
- return data;
44
- }
45
-
46
- //minor unresolved additional headlines
@@ -1,43 +0,0 @@
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();
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
- //////
20
- export function CHINATIMES($) {
21
- const data = $.extract({
22
- title: "h1.article-title",
23
- date: [
24
- {
25
- selector: "span.date:first",
26
- value: (el) => $(el).text().replace(/\//g, "-"),
27
- },
28
- ],
29
- source: { selector: "div.source", value: (el) => $(el).text().trim() },
30
- author: [{ selector: "div.author", value: (el) => $(el).text().trim() }],
31
- content: [
32
- {
33
- selector: "div.article-body p",
34
- value: (el) => {
35
- if ($(el).text().trim() !== "") {
36
- return $(el).text().trim();
37
- }
38
- },
39
- },
40
- ],
41
- });
42
- return data;
43
- }
@@ -1,34 +0,0 @@
1
- export function LTN3C($) {
2
- const data = $.extract({
3
- title: "div.whitecon.borderline.boxTitle.boxText h1",
4
- date: [
5
- {
6
- selector: "span.time",
7
- value: (el, key) => {
8
- const data = $(el).text().split(" ").slice(0)[0].replace(/\//g, "-");
9
- return data;
10
- },
11
- },
12
- ],
13
- author: [
14
- {
15
- selector: "span.author",
16
- value: (el) => {
17
- const data = $(el).text().split("").slice(-3).join("");
18
- return data;
19
- },
20
- },
21
- ],
22
- content: [
23
- {
24
- selector: "div.text p",
25
- value: (el, key) => {
26
- const text = $(el).text().trim();
27
- return text;
28
- },
29
- },
30
- ],
31
- });
32
- data["source"] = "自由時報"
33
- return data;
34
- }
@@ -1,40 +0,0 @@
1
- export function LTNEC($) {
2
- const data = $.extract({
3
- title: "div.whitecon.boxTitle.boxText h1",
4
- date: [
5
- {
6
- selector: "span.time:nth-of-type(1)",
7
- value: (el, key) => {
8
- const data = $(el).text().split(" ").slice(0)[0].replace(/\//g, "-");
9
- if (data != "") {
10
- return data;
11
- }
12
-
13
- },
14
- },
15
- ],
16
- author: [
17
- {
18
- selector: "div.text p:nth-of-type(2)",
19
- value: (el) => {
20
- const data = $(el).text().split("/")[0];
21
- return data;
22
- },
23
- },
24
- ],
25
- content: [
26
- {
27
- selector: "div.text p",
28
- value: (el, key) => {
29
- const text = $(el)
30
- .text()
31
- .trim()
32
- .replace(/〔.*?〕/g, "");
33
- return text;
34
- },
35
- },
36
- ],
37
- });
38
- data["source"] = "自由時報"
39
- return data;
40
- }
@@ -1,30 +0,0 @@
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
- }
@@ -1,26 +0,0 @@
1
- export function UDN($) {
2
- const data = $.extract({
3
- title: "h1.article-content__title",
4
- date: [
5
- {
6
- selector: "time.article-content__time",
7
- value: (el, key) => {
8
- const data = $(el).text().replace(/\//g, "-").slice(0, 10);
9
- return data;
10
- },
11
- },
12
- ],
13
- author: "a[href^='/news/reporter/']",
14
- content: [
15
- {
16
- selector: "section.article-content__editor p",
17
- value: (el, key) => {
18
- const text = $(el).text().trim();
19
- return text;
20
- },
21
- },
22
- ],
23
- });
24
- data["source"] = "聯合報";
25
- return data;
26
- }
@@ -1,35 +0,0 @@
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
- }
@@ -1,33 +0,0 @@
1
- export function CNA($) {
2
- const data = $.extract({
3
- content: [
4
- {
5
- selector: "div.paragraph > p",
6
- value: (el, key) => {
7
- return $(el).text();
8
- },
9
- },
10
- ],
11
- author: [
12
- {
13
- selector: "div.paragraph > p",
14
- value: (el, key) => {
15
- if ( $(el).text().includes("(中央社")) {
16
- let index = $(el).text().indexOf("記者");
17
-
18
- // Extract the 3 characters after "記者"
19
- return $(el)
20
- .text()
21
- .substring(index + 2, index + 5);
22
- // return index
23
- }
24
- },
25
- },
26
- ],
27
- });
28
- data["date"] = $('meta[property="article:published_time"]')
29
- .attr("content")
30
- .slice(0, 10);
31
- data["source"] = "中央社";
32
- return data;
33
- }
@@ -1,39 +0,0 @@
1
- export function ETDAY($) {
2
- const data = $.extract({
3
- title: "h1.title",
4
- date: [
5
- {
6
- selector: "time.date",
7
- value: (el, key) => {
8
- const date = new Date($(el).attr("datetime"));
9
-
10
- // Format the date to "YYYY-MM-DD"
11
- const formattedDate = date.toISOString().split("T")[0];
12
- return formattedDate;
13
- },
14
- },
15
- ],
16
- author: [
17
- {
18
- selector: "div > p:first",
19
- value: (el) => {
20
- const data = $(el).text()
21
-
22
- return data.replace(/.*記者(.{3}).*/, '$1');
23
- },
24
- },
25
- ],
26
- content: [
27
- {
28
- selector: "div.story > p",
29
- value: (el, key) => {
30
- // if (key > 1) {
31
- return $(el).text().trim()
32
- // }
33
- },
34
- },
35
- ],
36
- });
37
- data["source"] = "ETtoday"
38
- return data;
39
- }