Quantcast
Channel: WFU BLOG
Viewing all 571 articles
Browse latest View live

Google Apps Script 網頁爬蟲麻煩事交給 Cheerio 解決,輕鬆解析 HTML 與 XML

$
0
0
google-apps-script-parse-html-cheerio.jpg-Google Apps Script 網頁爬蟲麻煩事交給 Cheerio 解決,輕鬆解析 HTML 與 XML之前用 Google Apps Script(簡稱 GAS)製作網頁爬蟲程式,為了解析 HTML 與 XML 分別寫了兩篇心得:


其實前端環境用 jQuery 等函式庫處理 DOM 非常方便快速,習慣之後在後端處理 DOM 架構就會覺得很痛苦,要嘛想辦法自己做輪子,要嘛得學習駕馭別人另外做的變形輪子,如果後端也有 jQuery 可以用就好了。

有讀者留言提到 jsdom、cheerio 等關鍵字,這些都是 node.js 環境下用來處理 DOM 的 jQuery-like(仿 jQiery)模組。找了一下發現有國外網友做出用於 GAS 的 cheerio 版本,用了之後簡直是雨過天晴,後端也可以跟前端一樣輕鬆了,請見本篇 cheerio 的使用心得整理。



一、Cheerio 使用說明


1. 官網

首先這是 cheerio 的 node.js 官網:


這裡有官方詳細的介紹、操作說明,以及 Github 網址。

由於全部都是英文,而且跟本篇主旨 GAS 環境沒有任何關係,可以隨意看看就好。


2. 說明書

如果是英文苦手,可以閱讀這篇的簡中翻譯:


基本上如果會 jQuery 的話,不用看說明也會操作,基本常用的指令是一模一樣的。

但 cheerio 畢竟不等於 jQuery,如果有哪些 jQuery 操作方式不確定 cheerio 是否也有,就可以來這個網頁搜尋一下用法。



二、GAS 安裝 Cheerio


1. GAS 的 Cheerio 模組

在網路上找到 2 個 GAS 的 Cheerio 模組:

  1. cheerio-gasify
  2. cheeriogs

基本上第 1 個是原始版本,第 2 個是被 fork 之後的衍生版本,從 readme 說明來看也許功能比較強。

第 1 個 GAS 安裝說明完全沒有,第 2 個有 GAS 的安裝說明。然而結論是,測試的結果 2 個安裝後都無法直接使用。

經過多方測試後,第 1 個有找到解決方法,第 2 個找不出來,以下來看我怎麼調整第 1 個原始模組。


2. 安裝 cheerio-gasify

google-apps-script-parse-html-cheerio-1.png-Google Apps Script 網頁爬蟲麻煩事交給 Cheerio 解決,輕鬆解析 HTML 與 XML

首先按照第 2 個的安裝說明,先在 Google Drive 新增一個 GAS 專案,然後點選單上的「資源」→「程式庫」


google-apps-script-parse-html-cheerio-2.jpg-Google Apps Script 網頁爬蟲麻煩事交給 Cheerio 解決,輕鬆解析 HTML 與 XML

  • A:貼上前面第 1 個版本提供的 project key 字串 MU756IKHJ2hAYP1glQmzgA4ZBvzIux02r
  • B:版本選擇 cheerio@0.19.0
  • 按「儲存」即可


3. 修改呼叫函數字串

google-apps-script-parse-html-cheerio-3.jpg-Google Apps Script 網頁爬蟲麻煩事交給 Cheerio 解決,輕鬆解析 HTML 與 XML

上圖是官網提供的範例程式碼,但怎麼樣都無法執行,使用除錯模式後找到了原因,官網呼叫的函數 "cheerio_gasify"並不存在,從偵錯畫面可看到只有 "cheeriogasify"這個函數,所以應該是官網說明書的誤植。

把呼叫函數改成 cheeriogasify後果然就能正常執行了!



三、操作範例


1. HTML

直接拿第 2 個版本的程式碼,但改用原始版本的模組,來當作 HTML 範例程式碼:

function html_test() {
var cheerio = cheeriogasify.require('cheerio'),
response = UrlFetchApp.fetch("https://en.wikipedia.org"),
$ = cheerio.load(response.getContentText());

Logger.log($('#mp-right').text());
Logger.log($('p').first().text());
}

可自行測試看看,很方便就能用 jQuery 取得需要的 HTML 內容字串。


2. XML

之前這篇「Google Apps Script 使用 XmlService 解析 XML 要注意的地方」可看到,為了解析 XML 得瞭解一些複雜概念,現在使用 cheerio 什麼都不用懂,就像在操作 HTML 一般。

以下把之前 XmlService 的操作程式碼,直接改用 cheerio,真是簡單太多了:

function xml_test() {
var cheerio = cheeriogasify.require('cheerio'),
response = UrlFetchApp.fetch("https://www.youtube.com/feeds/videos.xml?playlist_id=UUgxXuXHJ4VwovSTvDiWlzZQ"),
$ = cheerio.load(response.getContentText()),
entries = $("entry"),
entry1 = entries.eq(0);

Logger.log(entry1.children("yt\\:videoId").text());
Logger.log(entry1.find("author name").text());
}

很方便就取得第一則影片的 id 以及標題,不過紅字這裡需要特別說明一下:

  • yt:videoId這個元素使用了命名空間(namespace) "yt",不能直接用 jQuery 直覺的作法
  • 例如 $("yt:videoId") 會取不到東西,因為冒號 ":"有特別的含意
  • 解決方法參考這篇「Explain \\: escaping colon for xml namespace pseudo」,有說明原理
  • 在冒號前面加上轉譯符號 "\\"兩個斜線,就可以把冒號 ":"視為字串了


更多 Google Apps Script 相關技巧:

讓 Blogger 導覽列的頁籤連結點擊後變色

$
0
0
blogger-nav-tab-color-change.jpg-讓 Blogger 導覽列的頁籤連結點擊後變色標題的意思也許不太容易能理解,不過搭配圖片就比較清楚了。可參考上方示意圖,出自「WFU 應用精選」,點擊導覽列上的「精選作品」進入該頁面後,這個頁籤的顏色會與其他頁籤不同,能清楚辨識出這個頁面顯示的文章、工具屬於什麼性質。

這功能 Blogger 不必另外寫程式也能做到,但有一些小問題需要解決,本篇會說明如何處理。




一、官方「標籤」小工具


如果「將 Blogger "標籤"小工具放在導覽列 」,可以實現這個效果,請參考該篇操作說明,版面效果則可參考分站「三國志 11」進行測試,例如下圖為點擊導覽列上標籤頁籤「火攻」的效果:

blogger-nav-tab-color-change-1.jpg-讓 Blogger 導覽列的頁籤連結點擊後變色

把「標籤」工具拉到導覽列雖然操作很方便,會自動出現 "頁籤"變色的效果,但缺點也很明顯:

  • 只能放「標籤」連結,無法放其他任何頁面的連結
  • 也不能放「首頁」連結



二、官方「網頁」小工具


若導覽列使用最常用的「網頁」小工具,彈性就比較大了,優缺點如下:

  • 優點:任何頁面連結、外部網址都能手動加入
  • 缺點:
    • 加入標籤頁籤稍微麻煩一點,要自行找出標籤頁面的連結
    • 而且使用標籤連結時,點擊進入標籤頁面後,頁籤不會變色

為了解決「網頁」小工具使用標籤連結時,進入標籤頁面不會變色的問題,必須修改範本官方 Blogger 語法才行。



三、修改範本


不熟悉語法的話,自行修改範本是非常危險的事,建議讀者先閱讀「備份範本的訣竅」系列文章,再進行以下動作。

備份完範本後,進入 Blogger 後台「主題」→「編輯 HTML」,游標點進範本區塊,按 Ctrl-F 搜尋「網頁」小工具的 ID,通常是 PageList1PageList2這樣的字串,如下圖:

blogger-nav-tab-color-change-2.jpg-讓 Blogger 導覽列的頁籤連結點擊後變色

  • 圖中可看到已找到「PageList1」這個小工具的區塊
  • 請注意 2 處紅色底線 data:link.isCurrentPage的 Blogger 語法,這就是代表「當網址為頁籤連結時」的意思
  • 然而「網頁」小工具此語法對 "標籤頁面連結"是無效的

因此請將 2 處紅色底線的字串,改為以下字串:

data:blog.canonicalUrl == data:link.href

這段 Blogger 語法的意思是「當頁面標準網址等於頁籤網址時」,此語法可相容每種頁面,包含 "標籤"頁面,以及行動版頁面。

改完後儲存即可看到效果。



四、注意事項


雖然以上語法在邏輯處理上都沒問題,但執行起來還是遇上一些麻煩:

  • 標籤使用「中文」字串時,data:blog.canonicalUrl所代表的網址,以及 data:link.href所代表的網址,其中一個會被編碼
    • 導致一個有中文字串、一個是英數字串,兩者字串不相等,所以頁籤無法變色
  • 另外連結網址也不可使用「相對網址」(省略 http 傳輸協定、或省略網域),必須使用「絕對網址」,也就是完整的 http 網址
    • 否則兩邊的字串一樣判定不相等


最後整理一下使用本篇這個功能時,需注意的地方:

  • 為文章另外設定「英文標籤」
  • 設定連結時需使用「絕對網址」


更多 Blogger 導覽列相關技巧:

Google Apps Script 操作 Google Photo API 上傳圖片實作心得

$
0
0
google-apps-script-photo-api-upload.jpg-Google Apps Script 操作 Google Photo API 上傳圖片實作心得自從「Google 關閉 Picasa API」之後,比較適合拿來存放圖片的免費空間變成「Google 相簿」。不過Google 為了不想被當成免費的外連圖床,Google Photo API 有不少限制,可參考這篇新聞「Google相片庫API正式上線,讓開發者在自家應用加入相簿功能」,裡面有提到:

Google特別提醒了開發者,在呼叫照片內容列表之後,應用程式應該儲存媒體檔案的ID,而非回傳的檔案本身,因為媒體檔案內容可能會有改變,並且在一定時間之後,回應的內容包括URL會過期

意思就是 API 取得的圖片外連沒有用處,一段時間後就會失效,這件事在「讓 Google Photo 實現相簿畫廊效果」也有提到。

所以 Google Photo API 主要的實質用途,在於上傳、搜尋圖片,至少可以把其他地方的圖片搬過來存放,不需要付費且嚴格來說沒有容量限制

但必須說 Google Photo API 很不好操作,之前處理「Gmail API」時已確立是最困難的 API 不會被超越,而此次使用 Google Photo API 也被整得灰頭土臉,榮登第二名的地位。本篇將說明在 Google Apps Script(簡稱 GAS)環境操作 API,如何上傳圖片到指定相簿的流程。



一、完整流程


一開始可先參考官網文件,瞭解 API 做些什麼事、如何開始:



都是英文可能很吃力,大致說明整個流程要做哪些事:

  • 取得 OAuth 驗證:
    • 啟用 API、取得 Client ID、密鑰
    • 申請永久 token,將來才不用每次重新驗證
  • 建立相簿:
    • 這一步非常重要,也是遇到的第一個大坑
    • 所有在「Google 相簿」官網上建立的相簿都無法用 API 上傳圖片
    • 只有用 API 建立的相簿才能上傳圖片
  • 上傳圖片:
    • 這是第二個坑,Google Photo 很不乾脆,不知為何要分兩個動作,上傳圖片後只能拿到一個 token
    • 接著要拿 token 在相簿裡面建立圖片物件,才能完成上傳
    • 容易掉坑的地方在於,不管上傳什麼都會拿到 token,即使圖片格式不對這一步都不會報錯。要等到最後一步「建立圖片物件」失敗時,讓你找不出究竟整個過程哪個動作錯誤,才導致無法成功建立物件。
    • 也許官方背後的意涵是,只要搞得越複雜,Google Photo 被拿來濫用的機率就越低
  • 建立圖片物件:最後一個坑,也是搞最久的一個地方,後面範例程式碼再說明



二、取得 OAuth 2.0 金鑰


OAuth 驗證的流程很長,包括「啟用 API、取得 Client ID、密鑰(Client Secret)、永久金鑰(refresh token)」,但取得 OAuth 並非本篇重點,為避免篇幅太長這部分將會簡單帶過,請參考以下參考資料,重點在於想辦法取得可永久使用的 refresh token:


如果是前端工程師的話,我相信有辦法可以搞定 OAuth、refresh token。真的沒辦法的話,有此需求的讀者請再留言反應,視需求程度再來寫 Google API 處理 Oauth 的通用流程。



三、建立相簿


前面說過了,必須使用 API 建立的相簿才能上傳圖片,所以首先請學習如何操作 API 建立相簿。參考官方文件:


此頁面有語法範例,也提醒前面走 OAuth 驗證時 scope 要至少有 photoslibrary才有寫入的權限。

非常棒的是,這個頁面就有控制台可以操作測試 API,往下捲就會看到:

google-apps-script-photo-api-upload-1.jpg-Google Apps Script 操作 Google Photo API 上傳圖片實作心得

  • A:在這裡設定好相簿標題就好
  • B:按下 EXECUTE 執行 API
  • C:這裡可看到 API 範例語法,將來照抄很方便
  • D:執行成功的話,建立相簿後紅色底線這裡會產生「相簿 ID」,將來上傳圖片需要用到此 ID
  • 可注意最下方紅框,isWriteable: true 代表這個相簿可寫入,才能上傳圖片

但是別被騙了,這裡是一個大坑,此處產生的「相簿 ID」一點作用都沒有,根本無法上傳圖片,原因在於這個相簿不是由我們的 APP 所產生,而是由控制台產生,所以我們沒有寫入的權限

所以之後得乖乖自己寫 code 來建立相簿,這樣產生的相簿 ID 才能用於上傳圖片。不過補充說明,把上圖「Google OAuth 2.0」、「API Key」都取消勾選,打開「Show standard parameters」,填入我們自己的 access_token,這樣就是由我們自己 APP 所建立的相簿,可上傳圖片。



四、上傳圖片


參考官方文件:



這裡詳細說明前面提到的「兩階段上傳」流程,以及語法範例、注意事項。大概整理一下要點:

  • 一次最多可上傳 50 圖,一張圖片最大 50MB,一個相簿最多裝 20000 張圖
  • 上傳的圖片格式必須為「raw bytes」
  • 依照 API 格式上傳完畢後,會返回一個字串「upload-token」,要記住這個字串
  • 依照 API 第二階段的格式,需要設定「相簿 ID」、輸入「upload-token」,有幸成功的話,這張圖片就會出現在相簿裡了
  • API 第二階段有個參數「albumPosition」可設定上傳圖片的位置,例如強制擺在相簿最前面,但我怎麼做都是出現在最後面,所以我認為這參數是裝飾用的。



五、建立圖片物件


官方很貼心的提供了控制台可操作,下面這個頁面捲到底就會看到:


但其實這功能只做了一半,因為只能跑第二階段的功能,也就是你要先自己寫 code 上傳完圖片,取得「upload-token」後,才能來這裡測試建立圖片物件的功能,挖勒...

總之官網的文件寫的很詳細,但沒有完整的實例,控制台測試功能也不完整。想要真正測試圖片上傳功能只能真的寫出 code 來才有辦法,那麼就直接來看範例程式碼吧。



六、GAS 範例程式碼


因為是在 GAS 環境操作,如果 GAS 不夠熟的話,要跳的坑就更多了,所以先看最大的坑怎麼解再看程式碼。

1. GAS 圖片的 raw bytes

從別處圖床搬到 Google Photo,可用 GAS 的指令 UrlFetchApp.fetch 爬圖片網址。爬回來後要如何轉換格式是一個大問題,究竟要丟什麼格式 Google Photo API 才吃只能不斷測試:

  • UrlFetchApp.fetch(imgUrl).getContentText() → 這是文字資料,不可以
  • UrlFetchApp.fetch(imgUrl).getContent() → 官方說明書說可返回 raw binary content → 實測 ok
  • UrlFetchApp.fetch(imgUrl).getBlob().getBytes() → 先取 blob 物件再轉 byte 格式 → 實測 ok


2. GAS 的 payload 格式

一般來說送出 post 的 request body,需要將物件用 JSON.stringify() 轉成字串。但實際使用 GAS 的 UrlFetchApp.fetch 送出 post 時,卻跟 Google Photo API 一直犯衝。

為了排錯,使用官方提供的同樣範例語法,在控制台操作可成功上傳圖片,特地改用前端的 jQuery Ajax 送出也都沒問題,但偏偏 GAS 送出就會報錯。

怎麼找到解法的過程、或原理就先略過了,總之 GAS 的 payload 格式不能用 JSON.stringify() 把 request body 轉換成字串,要直接手動作出 request body 的字串格式,才能被 Google Photo API 吃進去,來跳過這最後一個坑。


3. 範例程式碼

var photo_client_id = "xxxxxxxxxxxxxxxxxxxxx", // 填入自己的 Client ID
photo_client_secret = "xxxxxxxxxxxxxxxxxxxxx", // 填入自己的 Client Secret
photo_refresh_token = "xxxxxxxxxxxxxxxxxxxxx", // 填入自己的 refresh_token
albumId = "xxxxxxxxxxxxxxxxxxxxx", // 填入自己的相簿 ID
albumTitle = "WFU BLOG 測試", // 填入相簿描述
fileName = "WFUBLOG.jpg", // 填入圖片檔名
access_token = getAccessToken();

function uploadPhoto() {
var src = "https://1.bp.blogspot.com/-vhIWukZmniI/VA3My_ptRfI/AAAAAAAAKM0/DaF4uGRxB0Q/s200/wfublog-logo-8abeb7.png", // 這裡是上傳的圖片網址
uploadToken = getUploadToken(src),
uploadUrl = "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate",
data = '{"albumId":"' + albumId + '","newMediaItems": [{"description": "test","simpleMediaItem": {"fileName":' + fileName + ',"uploadToken":"' + uploadToken + '"}}], "albumPosition":{"position": "FIRST_IN_ALBUM"}}', // 若用 JSON.stringify(data) → google photo api 吃不到,自行轉成字串最保險
options = {
method: "post",
headers: {
"Authorization": "Bearer " + access_token,
"Content-Type": "application/json"
},
payload: data,
muteHttpExceptions: true
},
response = UrlFetchApp.fetch(uploadUrl, options);
Logger.log(response);
}

function getUploadToken(src) {
var rawData = getPhotoRaw(src),
options = {
"method": "post",
"headers": {
"Authorization": "Bearer " + access_token
},
"Content-type": "application/octet-stream",
"payload": rawData,
"X-Goog-Upload-File-Name": fileName,
"X-Goog-Upload-Protocol": "raw"
},
uploadRawUrl = "https://photoslibrary.googleapis.com/v1/uploads",
uploadToken = UrlFetchApp.fetch(uploadRawUrl, options);
return uploadToken;
}

function getPhotoRaw(src) {
var response = UrlFetchApp.fetch(src);
return response.getContent(); // 圖片轉成 raw binary 格式
}

function createAlbum() {
var album = {
album: {
title: albumTitle
}
},
url = "https://photoslibrary.googleapis.com/v1/albums",
options = {
"method": "post",
"headers": {
"Authorization": "Bearer " + access_token
},
"Content-Type": "application/json",
"payload": JSON.stringify(album)
},
response = UrlFetchApp.fetch(url, options);
Logger.log(JSON.stringify(response)); // 取得相簿 ID
}

function getAccessToken() {
var options = {
method: "post"
},
fetchUrl = "https://www.googleapis.com/oauth2/v3/token?client_id=" + photo_client_id + "&client_secret=" + photo_client_secret + "&refresh_token=" + photo_refresh_token + "&grant_type=refresh_token",
response = UrlFetchApp.fetch(fetchUrl, options),
results = JSON.parse(response.getContentText()),
access_token = results.access_token;
return access_token;
}

所有重點已用註解標示,以下依流程重點說明:
  • 先填入自己的 photo_client_id、photo_client_secret、photo_refresh_token,以及 albumTitle、fileName
  • 接著執行 createAlbum() 建立相簿,記下返回的相簿 ID,填入 albumId
  • 在 uploadPhoto 裡面可替換要上傳的圖片網址,接著執行 uploadPhoto() 就可上傳圖片到指定相簿


更多 Google Apps Script 相關技巧:


更多 Google Photo 相關文章:

協助 WordPress.com 搬家到 Blogger 記錄 + 問題解決

$
0
0
前陣子有 WP 網站想搬到 Blogger 而尋求協助,不過並非自架站 WordPress.org,而是免費的 WordPress.com。其實 WP 網站過去有處理過不少案件,但關於搬家的話倒是這兩者都沒實際搬過,等實際處理時才發現, WP.com 的難度還比較高。

因為 WP.com 在免費的前提之下,不允許修改範本、不能裝外掛,導致很多 WP.org 可以輕鬆處理的功能變得很困難,因此本篇做個簡單的筆記整理。

(圖片出處: pixabay.com)


一、搬家重點事項


一般來說搬家主要處理的項目有這些:

  • 搬文章
  • 搬圖片
  • 更換新舊文章連結
  • 搬人氣
  • 搬家畫面

其中「搬文章」是有可能不需寫 code,由站長自行處理的。而其他的項目,WP.com 提供了官方 API:


功能還滿詳盡的,有辦法寫程式的話都可以進行搬遷,否則就要請工程師處理了。



二、搬文章


1. RSS

由於 Blogger RSS feed 可取得所有文章資料,因此先從 WP RSS feed 下手,網址格式為:

http://xxx.wordpress.com/feed/

但可惜檢視資料後,WP feed 只包含最新的一些文章,無法含括所有文章,所以此路不通。


2. 線上轉檔工具

網路上有一些 WP 轉 Blogger 的線上工具,不過很難期待免費的線上網站能長久維護,很多都已失效。

目前這一個網站是還在運作的:


頁面上有操作步驟,從 WP 後台將文章匯出後,將檔案餵這個頁面,按「Convert」可產生一大堆 XML 檔,再從 Blogger 後台匯入。


3. 使用 WP API

一方面必須有線上服務隨時終止的心理準備,一方面轉換的檔案也很難預期可 100% 相容 Blogger 格式,那麼還是必須把操作 WP API 當成備案。

根據官方說明書,取得所有文章標題網址的語法如下:

https://public-api.wordpress.com/rest/v1.1/sites/WP網址名稱字串.wordpress.com/posts/?number=100&page=n&fields=title,URL

語法主要修改的地方有這些:
  • WP網址名稱字串
  • number 參數最多可填 100,代表一次取得 100 筆資料
  • page 參數代表第幾頁,例如填入 2 可取得第 101~200 筆資料
  • fields 參數填入 title,URL 代表取得標題、網址,若要取得其他欄位請參考說明書



三、其他項目


1. 其他項目

  • 搬圖片
  • 更換新舊文章連結
  • 搬人氣
  • 搬家畫面

以上這些項目都需要用程式處理,如果文章數不多的話也許可以手動自行處理。


2. SEO 301 轉址

如果是 WP.org 能修改後台、範本內容,那麼是可以 301 無痛移轉到新的 Blogger 網址,可參考「協助自架站、WP 搬家到 Blogger 流程紀錄」相關說明。

但 WP.com 無法裝外掛、改後台,那麼只好用製作「搬家畫面」的方式來逐漸移轉 SEO 到新網站,花的時間會多一些。



六、聯絡表單


如果有預算需處理 WP 搬家到 Blogger 事宜,請告知要搬家的項目有哪些:

  • 搬文章
  • 搬圖片
  • 處理新舊文章連結
  • 搬人氣
  • 搬家畫面、SEO 移轉


以及告知以下資訊:

  • 網址
  • 文章篇數


並用以下表單與本站聯繫:




更多部落格搬家相關文章:


更多 WordPress 相關文章:

從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

$
0
0
google-analytics-stats-save-to-google-spreadsheet.jpg-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作觀察網站各處連結的點擊成效,可以了解版面配置的效果、訪客的真正需求等等。要做到這件事,除了網站需要安裝 Google Analytics(簡稱GA),也需要使用「GA 事件追蹤器」這類程式。

之前製作「線上看電視」後,為了瞭解觀眾最喜歡收看哪些節目、戲劇、政論、卡通、甚至是音樂類型,決定做一個收視率報表,方便篩檢出熱門或沒人收看的節目,做為去蕪存菁的依據。

收集到的數據會存放在免費的 Google 試算表(資料庫),可做為 RSS FEED 用程式存取,本篇會說明取得報表數據的實作流程。



一、GA 工具


1. GA 報表

google-analytics-stats-save-to-google-spreadsheet-1.jpg-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

如上圖,從「GA 官網」→ 行為 → 事件 → 熱門事件,可取得相關的事件排序報表。

上圖為「戲劇」類節目收看排行報表,本篇會示範如何從 GA 撈這些資料,儲存到 Google 試算表。


2. GA 工具

官方提供了「GA API」可撈數據,比較麻煩的地方是, GA 可以撈的東西像海一般實在太多了,要快速找到該數據對應的參數、字串還滿麻煩的。

還好找到這個國外網友製作的工具,可以快速找到需要的參數代號:



google-analytics-stats-save-to-google-spreadsheet-2.png-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

進入該頁面後,從搜尋框輸入 "event"可過濾出「事件」相關的 GA 參數。如上圖,列出了 "Dimensions"、"Metrics"的所有參數,這些字串之後會用到。

當然讀者根可以據需求選擇對應的參數使用,而本篇用來舉例的資料,會使用到這些參數:

  • Event Action: 用來記錄事件的分類,例如「戲劇」(drama)
  • Event Label: 用來記錄事件名稱,例如節目名稱
  • Total Events: 該點擊事件的總數



二、Google 試算表操作


如果直接操作 GA API 的話會十分麻煩,要取得 API 金鑰、驗證 OAuth 等等,如果不是前端工程師、不會寫 code 的話,這部分可能就要卡很久了。

值得慶幸的是,Google 試算表提供了許多外掛可安裝,其中最好用的外掛就是「Google Analytics」,讓我們不用寫程式就可取得 GA 數據報表。


google-analytics-stats-save-to-google-spreadsheet-3.png-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

首先進入「Google Drive」建立一個空白試算表,接著安裝外掛。

如上圖,點選「外掛程式」→「取得外掛程式」


google-analytics-stats-save-to-google-spreadsheet-4.jpg-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

在搜尋框輸入「google analytics」,搜尋結果第一個(如上圖紅框)就是了。

點選後開始安裝,過程中會問很多次選項,總之全部按允許、同意就好了。


google-analytics-stats-save-to-google-spreadsheet-5.png-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

安裝成功後,在上圖「外掛程式」會多出一個「Google Analytics」的項目,點擊「Create new report」開始建立 GA 報表。


google-analytics-stats-save-to-google-spreadsheet-6.jpg-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

  • A:填入存放數據的工作表名稱
  • B:選擇自己的 GA 網站帳號
  • C:這裡選擇所有前面看到過的 Metrics 參數,可輸入 event 能快速篩選參數
  • D:這裡選擇所有前面看到過的 Dimensions 參數,可輸入 event 能快速篩選參數
  • 最後按「Create Report」


google-analytics-stats-save-to-google-spreadsheet-7.jpg-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

  • A:會自動產生一個工作表「Report Configuration」
  • B:這裡可設定數據開始日期,請按字面上的邏輯輸入即可,例如要取得過去一週資料可改成 "7daysAgo"
  • C:這裡可設定數據結束日期,請按字面上的邏輯輸入即可
  • D:檢查一下這裡產生的所有 Metrics 參數,是否跟前面國外的「GA 工具」看到的字串一致,以免選錯了
  • E:檢查一下這裡產生的所有 Dimensions 參數,是否跟前面國外的「GA 工具」看到的字串一致,以免選錯了
  • F:這裡可修改要取得的數據筆數
  • G:點擊選單上的「外掛程式」→「Google Analytics」→「Run reports」可開始撈資料



三、後續操作


1. 整理報表

google-analytics-stats-save-to-google-spreadsheet-8.jpg-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

切換到「一週統計」這個工作表,可看到 GA 數據都已經撈過來了,接著可以用試算表的預設功能來整理數據。

例如點選上圖 15 行後,點擊選單的「資料」→「建立篩選器」,上圖可看到只篩選「戲劇」(drama)的節目來顯示,並在「Total Events」那一欄使用排序,讓最熱門的節目排在前面,這個報表是不是就跟前面在 GA 看到的圖一模一樣了!


2. 定期更新

為了讓 Google 試算表定期更新 GA 數據,回到「Report Configuration」工作表,點擊選單「外掛程式」→「Google Analytics」→「Schedule reports」

google-analytics-stats-save-to-google-spreadsheet-10.png-從 Google Analytics 撈點擊事件數據報表,儲存於 Google 試算表實作

勾選「Enable reports to run automatically」,如上圖,選擇想要更新的頻率,最後按「Save」即可。

雖然這個外掛允許勾選「Every Hour」每小時更新,畢竟 Google 佛心地提供免費服務,如非必要還是不要讓 Google 伺服器太忙碌比較好,珍惜免費資源所有人才能用得更久。

而且根據我的經驗,勾選每天更新比較不會報錯,否則 Google 伺服器太忙碌有時就不執行了


3. 存取試算表

後端資料庫存放的數據,最終還是要提供給前端使用才有意義,而如何存取 Google 試算表的資料,過去我已經寫了一系列文章,請直接參考即可:



更多 Google Analytics 相關技巧:


更多 Google 試算表相關文章:

Blogger 設定 ads.txt 常見問題整理

$
0
0
blogger-adsense-ads-txt-problems.jpg-Blogger 設定 ads.txt 常見問題整理Blogger 社團有幾個關於 Adsense 會顯示 ads.txt 錯誤訊息的提問與討論,其中某些案例看起來很難解決,因為牽涉到 Blogger 後台設定與網址代理商後台的 DNS 設定,由於權限的關係旁人無從得知實際狀況,只能憑空猜測,所以最終還是只能靠案主自己找出問題所在。

而前陣子「線上看電視」買了新網域後,無論是 Blogger 後台或 Google Domains 後台的 DNS 設定都有變更,導致短暫發生了 ads.txt 的錯誤訊息。當解決問題後,跟 Blogger 社團的案例交叉比對算是有了眉目,本篇就做個整理。



一、ads.txt 的用意與說明


首先參照官方文件「Ads.txt 指南」的說明:

Authorized Digital Sellers (簡稱 ads.txt) 是美國互動廣告局 (IAB) 主持的一項計劃,旨在確保您的數位廣告空間只透過獲得您授權的賣家 (例如 AdSense) 出售。您可以藉著建立專用的 ads.txt 檔案,更全面地控管哪些人有權在您的網站上銷售廣告,以免廣告客戶買到假冒的廣告空間。

強烈建議您使用 ads.txt 檔案,因為它能幫助買家辨識假冒的廣告空間,並確保您能收到買家購買您的廣告空間時支付的費用。

簡單用白話說一下以上這一大段背後代表的意思:

  • 有少數不肖廣告代理商,把某些不能賣的廣告曝光欄位賣給廣告主,這個 "不能賣"的意思是,該廣告代理商在某些網站沒有展示廣告的權利
  • 如果剛好我們的網站不能展示某些廣告代理商的廣告,而廣告代理商又把這些廣告曝光機會賣給廣告主,那麼廣告主就會白花廣告預算費用
  • 那麼我們的網站就算展示這些廣告依然拿不到收益
  • 而設定了 ads.txt 後,可以避免我們網站展示拿不到收益的廣告,壓縮可拿到收益的廣告展示機會

ads.txt 立意是良好的,而看起來成效是取決於所謂 "不肖廣告代理商"有多少,"不能展示的廣告曝光機會"有多少,我認為比例應該很低,我相信 Adsense 會有很好的控管,尤其 ads.txt 現在又大張旗鼓實施後,比例應該更低了。

我要表達的意思是,既然機率不高,那麼 ads.txt 如果設定出現錯誤訊息,其實也不是什麼需要非常緊張的事,應該影響 Adsense 收益沒多少錢。除非你的收益每月好幾百美金,那麼就有必要讓 ads.txt 沒有錯誤訊息。



二、Blogger 後台設定


這個 Blogger 社團案例詢問「ads.txt 要如何處理」,並附上 adsense 後台的錯誤訊息畫面。

解決方式在 Blogger 後台直接設定即可,劉玲君的說明內容很清楚,在 Adsense 後台取得自己的 ads.txt 內容後:

把底下這一行貼在Blogger後台→設定→搜尋偏好設定,找到營利下的自訂 ads.txt,啟用它之後按下編輯貼入框中儲存。(其中的pub-開頭字串,請換成您自己的發佈商編號)

google.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0

儲存變更之後,Google會在24小時內掃描一次,最晚72小時內會掃描完畢,確認有正確放置ads.txt之後,這個訊息就會自動消失了。

需要圖片說明的話,請看文章開頭的圖片。



三、自訂網域設定


1. 為何自訂網域會出現錯誤訊息

這個 Blogger 社團案例詢問「自訂網址 ads.txt 要如何處理」,討論串很長,大致摘要一下:

  • 有很多 Blogger 自訂網址都會收到 Adsense 提示的 ads.txt 錯誤訊息
  • 其中 悠樂玩家提供了跟 Adsense 的詳細往來過程,其案例很有參考價值
  • 原本他的網址 https://tainanlohas.cc 有些設定沒有完善,導致無法正確轉址到 https://www.tainanlohas.cc
  • 之後 DNS 後台有設定 4 個 A 記錄,並在 Blogger 後台有勾選裸網域轉址到 www 子網域,ads.txt 錯誤訊息就消失了
  • 此討論串剛好有一個反例,http://wanghenry.com/ 這個網址當下無法轉址到 www 子網域,所以會出現 ads.txt 錯誤訊息

所以結論很清楚:自訂網址只要能成功將裸網域轉址到 www 子網域,那麼 Adsense 就能成功讀取 ads.txt,而不會出現錯誤訊息


2. 如何正確設定自訂網址

Blogger 設定自訂網址的正確方法,可參考「Blogger 自訂網址」→「二、主網域設定」:

A. 參考「Blogger 官網說明」的步驟進行

B. 流程最重要的是,必須將 4 個 A 記錄設定正確,如此裸網域才能正確轉,例如下圖為 WFU BLOG 以前在 Godaddy 的設定畫面──




C. 最後要在 Blogger 後台勾選將裸網域轉址到 www 子網域,如下圖──



以上最麻煩的是在網址代理商的 DNS 後台設定,因為每家的介面都不一樣,所以不會有標準答案,只能自己想辦法找教學,或是聯絡客服人員,畢竟都已經付了錢,客服有義務幫我們解決 DNS 問題。



四、blogspot.com 錯誤訊息


在前面「二、Blogger 後台設定」的社團討論串中,有人提到 xxx.blogspot.com、xxx.blogspot.tw 等等非自訂網域的網站,會出現 ads.txt 錯誤訊息,而最近我也在後台看到了:

blogger-adsense-ads-txt-problems-1.jpg-Blogger 設定 ads.txt 常見問題整理

這應該是在本站買 wfublog.com 網址之前所建立的 adsense 廣告單元,所使用的 blogspot.com 網址,但不太可能去處理這個,因為現在用的是自訂網址。如果真的要做的話,大概是這樣吧:

  • 重新建立自訂網域的廣告單元
  • 再刪除 blogspot.com 的廣告單元
  • 網站 adsense 安裝碼改用新的廣告單元


那麼,如果有錯誤訊息潔癖的話,可以按以上方式試試看。

另外找到一篇國外的討論串「How to fix ads.txt file issues for Blogger」,出現了各種 blogspot 網址後綴的 ads.txt 錯誤訊息,而最佳解答跟我的想法差不多,直接無視就好了,因為 blogspot 網域不是我們可以控制的。



五、總結


簡單總結本篇的各種 ads.txt 錯誤狀況:

  • xxx.blogspot.com:在 Blogger 後台設定好即可
  • 自訂網址:必須將 DNS 設定好(包含 4 個 A 記錄),Blogger 後台也要將裸網域設定為轉址到 www 網域,只要裸網域能成功轉址就沒問題
  • 自訂網址但出現 xxx.blogspot.xxx 錯誤訊息:請無視沒關係


更多 Adsense 相關技巧:

製作網路爬蟲工具抓動態產生的網頁資料﹍體育賽事範例實作

$
0
0
web-crawler-ajax-data.jpg-製作爬蟲工具抓動態產生的網頁資料﹍體育賽事範例實作之前記錄了幾篇「Google Apps Script 製作爬蟲工具」的心得,使用 cheerio 套件之後,解析網頁的 HTML/XML 內容變得十分輕鬆。

但越來越多網頁使用 Ajax 動態載入資料內容,這些由 Javascript 產生的內容在網頁原始碼是看不到的,那麼爬蟲自然也爬不到。真要取得動態產生的 JS 內容,需要使用不一樣的技巧,本篇將分享 NBA 賽事數據實作心得整理。

(圖片出處: NBA)


一、原理


這篇「Python爬蟲·AJAX動態頁面的解析」已經將操作原理說明得很清楚了,簡單整理一下:

  • 使用 Chrome 開發人員工具
  • 從 Network 觀察動態載入資料的連結是哪個
  • 將爬蟲工具改為爬動態載入的那個網址
  • 對取得的資料進行解析即可

瞭解原理後,技術上來說取得動態載入的資料變得一點都不困難,只是換個網址來爬而已。

但實作後發現困難之處還是有,除了判斷抓哪個網址,還可能有比爬資料更棘手的問題要解決,真的需要靠經驗累積才能找到訣竅。



二、NBA 官網範例


以下使用 NBA 官網來做範例,進入 NBA 比分戰況頁面:



web-crawler-ajax-data-1.jpg-製作爬蟲工具抓動態產生的網頁資料﹍體育賽事範例實作

  • 可惜時間還太早,比賽都還沒開始,所以看不到任何比分數據。
  • 不過沒關係,打開「Chrome 開發人員工具」→ 切換到「Network」頁籤,我們要觀察頁面會載入哪些資料
  • 接著比賽日期切到前一天,由於 NBA 官網不會切換頁面,而是使用 Ajax 動態取得數據,我們看看 Network 會得到什麼資訊


web-crawler-ajax-data-2.jpg-製作爬蟲工具抓動態產生的網頁資料﹍體育賽事範例實作

  • 畫面上紅框處看到前一天的「獨行俠 vs 火箭」比賽結果 137:123,Doncic 與 Harden 兩位明星各自都有十分傑出的演出。
  • 在 Network 我們運氣很好,第二個載入的檔案 scoreboard.json 這檔名看起來就像裝了我們要的比賽數據資料,而且以 json 格式儲存,將來處理更加方便
  • 右邊「Headers」欄位紅色底線處,可看到這個檔的完整連結,我們就來看看裝了什麼內容


web-crawler-ajax-data-3.jpg-製作爬蟲工具抓動態產生的網頁資料﹍體育賽事範例實作

  • 切換到「Preview」可預覽檔案內容
  • 上方紅色底線可看到比賽場館在休市頓的 Toyota 中心,八成就是我們要找的這場比賽
  • 下方紅框有 Doncic、Harden 的本場數據,跟網頁上的資料一模一樣,可以確定這個檔能撈到所有我們需要的比賽數據



三、反爬蟲機制


1. 禁止存取數據

接著準備爬 json 資料吧,試著把前面取得的 json 連結用瀏覽器叫出來看看內容:

https://data.nba.net/prod/v2/20191224/scoreboard.json

web-crawler-ajax-data-4.png-製作爬蟲工具抓動態產生的網頁資料﹍體育賽事範例實作

真糟糕,怎麼只有這短短幾行,跟剛剛看的完全不一樣!根本沒有取得任何數據啊~~

無論是什麼原因,也許呼叫該網址要存取 cookie,也許有限制存取網域,總之 nba.com 有反爬蟲機制,不給輕易爬取資料,那麼該怎麼辦呢?


2. 找別的網站

我相信高手有辦法反制各種限制,而我的想法是,找出破解方法的時間,應該是遠高於換一個網站爬的時間,畢竟存放 NBA 比賽數據的網站多到數不清。

舉例來說,測試了「中國 NBA 官網」後,發現網站並沒有擋爬蟲,那麼使用以下的網址就能成功取得數據:

  • 比賽網址:https://china.nba.com/scores/#!/比賽日期
  • 數據 json:https://china.nba.com/static/data/scores/daily_比賽日期.json


以上日期都是 YYYY-MM-DD 格式,例如這個網址可取得 2019-12-24 數據:

https://china.nba.com/static/data/scores/daily_2019-12-24.json



四、總結


簡單總結一下本篇爬蟲 Ajax 數據心得:

  • 從爬取網頁原始碼改為尋找儲存數據的連結網址
  • 利用 Chrome 開發人員工具的 Network,分析動態載入的連結
  • 練習從檔名、網址結構找到正確的目標
  • 如果遇到反爬蟲的網站,換個網站爬


更多爬蟲工具相關技巧:

查詢網站熱門關鍵字的管道有哪些?

$
0
0
find-web-popular-keywords-google-analytics-search-console.jpg-查詢網站熱門關鍵字的管道有哪些?熱門關鍵字就像訪客身上掉落的麵包屑,不經意透露了行徑的路線與意圖。如果想知道自己網站如何吸引客人拜訪、又去了哪裡,記得不定時到門口看看地上痕跡,找找有哪些麵包屑。

Google Analytics(簡稱 GA) 是記錄這些物證的最佳工具,不過近年來能夠調閱的資料越來越少。沒了這個強大的工具,站長們不免心慌,畢竟訪客不會主動顯露他們的意圖。

然而 Google 大神關了一扇窗,卻也開了另一扇門,所以站長們可先安心,本篇會說明如何找出訪客是藉由哪些關鍵字認識我們的網站。

(圖片出處: pexels.com)


一、為何 GA 無法查閱關鍵字


GA 會記錄訪客從搜尋引擎而來的關鍵字,例如從「GA 官網」→「客戶開發」→「所有流量」→「來源/媒介」→「關鍵字」,可看到以下畫面:

find-web-popular-keywords-google-analytics-search-console-1.jpg-查詢網站熱門關鍵字的管道有哪些?

不過令人沮喪的是,只能看到一小部分的關鍵字資料,大概只佔了 2% 的搜尋記錄而已,有 98% 的資料都是 (not provided)、(not set)。這些 GA 不提供的資訊,名詞定義可參考「GA的(not set)與(not provided)是什麼?」,簡單摘要:

  • not provided:來源為 Google 搜尋引擎,因為隱私保密的緣故不提供關鍵字,但 AdWords 付費用戶可看到
  • not set:來源非搜尋引擎而來,所以沒有關鍵字資料


為何 GA 會顯示 "not provided",其源由可參考這篇「GOOGLE 將全面預設為安全資料傳輸層(SSL)搜尋」:

  • Google 推廣安全資料傳輸層(SSL)搜尋,在資訊傳輸過程中不紀錄用戶的相關行為數據。
  • 近一兩年 Google 為了達此目的,使用 Chrome 瀏覽器會強制對非 HTTPS 網站顯示 "不安全"的圖示,迫使 HTTPS 網站越來越多
  • 這也代表我們能從 GA 查看到的關鍵字數據越來越少
  • 這篇文章表示,GA 能看到的關鍵字只能收集自 Bing、Yahoo 及 Google 以外的搜尋引擎,那麼資訊當然越來越少了



二、從 Google 網站管理員取得關鍵字


1. 舊版 GSC

可參考「面對搜尋進站關鍵字 (NOT PROVIDED) 的解決方案」,同樣是 Google 產品,網站管理員 Google Search Console(簡稱 GSC) 倒是保留了關鍵字數據資料,雖然 GSC 能做的事沒有 GA 多,不過能檢視關鍵字就值得萬幸了。

從過去的文章會發現,舊版 GSC 的關鍵字報告只保留了「90 天」,使用關鍵字功能時必須戰戰兢兢,只要一段時間沒進 GSC 就會錯失前陣子的關鍵字潮流趨勢。


2. 新版 GSC

不過現在只要進入舊版 GSC,一律還是導向「新版 GSC」,且新版的關鍵字數據區間已放寬到 16 個月,已經大大抒解之前的窘境:

find-web-popular-keywords-google-analytics-search-console-2.jpg-查詢網站熱門關鍵字的管道有哪些?

點擊預設的「前 3 個月」區間


find-web-popular-keywords-google-analytics-search-console-3.jpg-查詢網站熱門關鍵字的管道有哪些?

選擇「前 16 個月」→「套用」即可


3. 備份 GSC 資料

如果覺得 16 個月還是不夠用,有長期觀察關鍵字的需求,可參考這篇「用Google試算表整理Search console關鍵字資料」,利用試算表來定期自動儲存 GSC 的數據。



三、GSC 使用技巧


1. 關鍵字操作

find-web-popular-keywords-google-analytics-search-console-4.jpg-查詢網站熱門關鍵字的管道有哪些?

左側選單「成效」→「查詢」,就可列出網站最熱門的關鍵字。


find-web-popular-keywords-google-analytics-search-console-5.jpg-查詢網站熱門關鍵字的管道有哪些?

還可找出搜尋關鍵字而來的最熱門頁面,如上圖將頁籤切換到「網頁」,以圖中紅框這個網址為例,點進該網址──


find-web-popular-keywords-google-analytics-search-console-6.jpg-查詢網站熱門關鍵字的管道有哪些?

就會列出所有訪客進入該頁面所使用的關鍵字為何。


2. 應用方式




四、付費工具


如果是商業網站,GSC 可能不敷使用,因為更多需要的是瞭解競爭對手使用的關鍵字數據、趨勢等資訊,那麼就非使用付費工具不可,可參考這些工具:



更多 Google 網站管理員使用技巧:


更多 SEO 相關技巧:

Google 搜尋結果無法出現麵包屑的原因研究

$
0
0
breadcrumb-search-result-not-found.jpg-Google 搜尋結果無法出現麵包屑的原因研究過去在「輕鬆讓 Blogger 搜尋結果出現麵包屑導航」提供了安裝程式碼,基本上只要在「Google 結構化資料測試工具」沒有錯誤,那麼在搜尋結果出現麵包屑導航關鍵字沒什麼問題。

不過最近出現一個案例,安裝了程式碼後,只有少部分文章可以在搜尋結果顯示麵包屑,大部分文章都失敗,這現象滿奇特的。基本上少部分文章能顯示的話,代表程式碼的執行沒問題,只是為何這些結構化資料語法對大部分文章不起作用,將是本文要探究的原因。

(圖片出處: pixabay.com)


一、沒有麵包屑導航的狀態


這是沒有安裝麵包屑語法的案例,Google 搜尋以下字串可列出所有結果:

site:playpcesor.com

breadcrumb-search-result-not-found-1.jpg-Google 搜尋結果無法出現麵包屑的原因研究

上圖畫紅線之處,就是 "預設"的麵包屑導航效果,例如第一篇文章的網址為:

https://www.playpcesor.com/2014/03/evernote.html
  • "預設"的麵包屑就是直接拿網址 "2014/03"、"evernote"等字串來充當麵包屑,效果當然不會很好。
  • 但網址如果用心命名的話還是對 SEO 些幫助,例如該篇文章與 evernote 相關,而網址設定了 "evernote.html",至少麵包屑能顯示一個有意義的字串 "evernote"
  • 那麼對於訪客搜尋 "evernote"相關文章時,還是有稍許加分的效果

本篇要探討的是,裝了麵包屑語法後,為何仍然出現上圖的狀況。



二、假設 1:麵包屑需與內文高度相關


以本站 WFU BLOG 為例,有安裝麵包屑導航語法的情況下,Google 搜尋以下字串可看到──

site:www.wfublog.com

breadcrumb-search-result-not-found-2.jpg-Google 搜尋結果無法出現麵包屑的原因研究

  • 上圖可看到每篇文章在搜尋結果,都成功顯示了麵包屑導航字串
  • 這些麵包屑字串,都是依據該篇文章的標籤字串來設定
  • 同時無論是標題、文章內容,看起來都與標籤(也就是麵包屑)字串有高度相關

所以我的初步假設為,搜尋結果會顯示的麵包屑字串,Google 會檢查是否與文章內容、或是標題有高度關聯

如果站長為了搶某些關鍵字,為文章使用了特定標籤,並設為麵包屑字串,但 Google 判斷該字串與文章或標題的關聯性沒那麼緊密時,則搜尋結果可能不顯示麵包屑。



三、假設 2:麵包屑需要 Google 信任該網站


以本站開發的「線上看電視」為例,有安裝麵包屑導航語法的情況下,Google 搜尋以下字串可看到──

site:tv.wfuapp.com

breadcrumb-search-result-not-found-3.jpg-Google 搜尋結果無法出現麵包屑的原因研究

  • 同樣可看到每篇文章在搜尋結果,都成功顯示了麵包屑導航字串
  • 這些麵包屑字串,也都如實顯示了該篇文章設定的標籤
  • 但不太一樣的地方是,紅線標示的那些標籤字串,看起來不一定與節目名稱或內容相關度那麼高
  • 因為那是我為這些節目所設定的群組分類字串,並非按照節目的特質來設定標籤字串

也因為看到了這樣的結果,等於推翻了我前面的假設「搜尋結果會顯示的麵包屑字串,Google 會檢查是否與文章內容、或是標題有高度關聯」

根據新的事證,我將假設調整為:

  • 搜尋結果會顯示的麵包屑字串,取決於 Google 是否信任該網站
  • 如果 Google 信任該網站,文章設定什麼麵包屑字串,都會在搜尋結果顯示出來



四、案例分析


文章開頭的案例為了保護隱私,不列出截圖或相關網址。經過詳細審視搜尋結果的每篇文章,發現大部分無法顯示設定好的麵包屑導航字串,只有少數文章可顯示。

將這些少數文章進行交叉比對,結論推測如下:

  • 該網站由於長期關注 SEO 技巧,可能做過某些舉動、或持續使用某些手法,讓 Google 覺得有操縱 SEO 排名的意圖
  • 因此成為 Google 不夠信任的網站
  • 這些少數文章之所以能夠顯示設定好的麵包屑字串,共通點都是麵包屑與標題或內文有高度相關
  • 推測當 Google 不夠信任該網站時,麵包屑只要與標題或內文的相關度不夠高,就只能顯示 Google 預設的麵包屑效果



五、其他見解


在想辦法歸納結論的過程中,也查找了相當多的資料與不同意見,整理一些做為參考:

1. 這篇「Breadcrumbs not displaying on Google」討論串的意見是這樣:

  • 經觀察麵包屑出現的規則,我認為主要是 Google 說了算,
  • 如果某些文章無法出現麵包屑,只能等待而已
  • 就算安裝碼正確,Google 不總是顯示設定好的麵包屑,因為 Google 只會顯示對搜尋者最有幫助的資訊
  • 似乎一部份取決於 Google 是否信任該網站/網頁、權重、流量等等


2. 這篇「Breadcrumb List result not showing on google search result」討論串的意見是這樣:

  • Google 不保證會顯示設定好的麵包屑字串,他們會做各種實驗測試效果。



六、總結


去年曾寫過一篇「Google 搜尋結果顯示的文章縮圖,跟你想的不一樣」,其中很重要的案例是,Google 會根據不同的搜尋關鍵字,提供最適切的縮圖給搜尋者。

跟本篇的心得交互驗證,倒是可以得出一個關鍵概念:

  • Google 的終極目標是找出搜尋者最需要的資訊並顯示出來,而非站長們想要顯示給搜尋者的資訊

所以,如果站長們刻意營造出來的資訊,剛好被 Google 顯示出來了,代表 Google 也認同這樣的想法,那麼可以往那個方向繼續努力。

如果無法被 Google 顯示出來,也無須氣餒,畢竟市場不是我們能夠憑空揣測的。只要想辦法瞭解搜尋者需求,以滿足搜尋者為第一目標,總有一天會得到 Google 認可的。


更多 SEO 相關技巧:

如何從 Google Analytics 站內搜尋數據瞭解訪客需求?

$
0
0
google-analytics-site-search.jpg-如何從 Google Analytics 站內搜尋數據瞭解訪客需求?網站經營的風格與內容走向,通常取決於網站主題或站長意願,例如 WFU BLOG 主要是記錄筆記心得的部落格,沒有追求流量,那麼內容寫什麼、不寫什麼,或是多久更新,不太會被某些數據所左右。

不過做了「線上看電視」之後,由於這是個極度民生導向的平台,必須時時刻刻瞭解觀眾喜好,不太可能自己想看什麼節目才擺上去,不想看的就不放,否則客群很快就流失了。

而如何精確找出觀眾的需求,需要使用科學方法,而非自己的想像。本篇會分享十分有效的工具,只要網站安裝了 Google Analytics(簡稱 GA),就可輕鬆取得這些重要資訊。



一、熱門關鍵字與站內搜尋的差異


瞭解訪客需求主要有 2 種管道:熱門關鍵字(keyword)與站內搜尋。

1. 熱門關鍵字

前陣子寫過這篇「查詢網站熱門關鍵字的管道有哪些」,說明如何利用 Google 網站管理員(search console),找出訪客是搜尋了哪些關鍵字而找到我們網站。

為了方便釐清概念,我稱這個管道為「歷史需求」,代表:

  • 這些熱門關鍵字可以讓我們瞭解,網站過去滿足了哪些訪客的需求
  • 我們能知道網站有哪些熱門內容、現有資訊,足以吸引到訪客的目光。
  • 只要多寫這些熱門關鍵字的文章,就足以逐步擴大網站的基本盤。


2. 站內搜尋

而本篇的主題「站內搜尋」,則是收集訪客利用網站提供的搜尋框,留下的所有搜尋字串紀錄。只要網站有安裝過 GA,就能在 GA 官網查詢這些「站內搜尋」資料。

為了方便釐清概念,我稱這個管道為「未來需求」,代表:

  • 這些站內搜尋字串可以讓我們瞭解,訪客想在我們網站找到什麼資訊。
  • 當然一部份資料有可能跟「熱門關鍵字」雷同,但一定有許多搜尋字串是我們想不到,且「熱門關鍵字」所找不到的,也就是網站還沒有提供的內容
  • 這代表「站內搜尋」是訪客為我們網站創造的未來需求。
  • 如果有辦法滿足這些空缺的需求,就等於我們跨出了基本盤,網站得以開闢新的疆土


3. 比較

定期查詢「熱門關鍵字」算是 "固本",知道寫哪些文章可以抓緊網站的基本盤。

而重視「站內搜尋」則是 "開源",如果網站基本盤已經穩了,成長規模開始撞牆,那麼「站內搜尋」可以讓我們知道,寫哪些文章可以突破邊際效益。

那麼在我看來,網站經歷不同的成長週期後,「站內搜尋」的資訊會比「熱門關鍵字」更值得重視。



二、從 GA 取得站內搜尋資訊


1. 準備動作

要取得 GA 的站內搜尋數據,準備動作如下:

  • 網站需安裝 GA
  • 網站需有搜尋框
  • 且搜尋框送出的字串,要能讓 GA 接收到資訊

通常部落格平台都會有官方搜尋工具可安裝,如不會安裝搜尋工具,請恰專業人士處理。


2. GA 設定

詳細步驟請參閱官網文件「設定站內搜尋」,以下簡單說明步驟:

進入「GA 官網」→ A.「管理」→ B.「資料檢視設定」

google-analytics-site-search-1.jpg-如何從 Google Analytics 站內搜尋數據瞭解訪客需求?

如上圖,完成 A、B 後:

  • C:啟用站內搜尋追蹤
  • D:輸入查詢參數,以 Blogger 平台為例,輸入 "q"即可
  • 最後按「儲存」

如不知你的網站要輸入什麼查詢參數,請恰專業人士處理。

完成以上流程後,GA 就能接收所有訪客站內搜尋使用的字串,接下來我們來看 GA 報表。



三、站內搜尋範例


進入「GA 官網」→「行為」→「站內搜尋」

google-analytics-site-search-2.jpg-如何從 Google Analytics 站內搜尋數據瞭解訪客需求?

如上圖,就能看到訪客搜尋最多的字串是哪些。

舉例來說,「1. 想見你」、「17. 苦力」、「21. 天堂的微笑」,這幾個都是「線上看電視」原本沒有收錄的戲劇節目,現在從站內搜尋瞭解了觀眾的需求後,就可以加入這些節目,創造更多客源。



四、總結


若沒有「站內搜尋」的數據,我們很可能會憑空想像訪客有什麼需求,自行創造一堆也不知道有沒有市場的需求,白花許多時間臆測。

有了「站內搜尋」做為指引,我們便可將時間花在刀口上,先處理訪客真正會有的需求,行有餘力再來進行未知市場的開發。

補充:Blogger 平台若處理搜尋工具有困難,可再聯繫本站。


更多 Google Analytics 相關技巧:

使用 Safari 可能無法在 Blogger 網站留言﹍聊聊 cookie

$
0
0
safari-blogger-comment-fail.jpg-使用 Safari 可能無法在 Blogger 網站留言﹍聊聊 cookie幾個月前「Blogger 社團」有成員反應表示她的 Blogger 網站無法留言,這現象看起來挺離奇,因此花了一些時間辦案。 雖然最終水落石出,但對於結果感覺不是很舒服,因為這是「蘋果 MAC」體系的一個難解現象。

早期前端開發人員、站長們對於 IE 的網頁相容性很頭痛,好不容易現在 IE 被淘汰了,結果「蘋果」的 Safari、iOS 系統取而代之。

過去為了方便處理蘋果的作業環境,我寫過一些文章,例如「利用 Chrome 對 iOS 裝置進行除錯」。那麼本篇除了做為記錄,也順便聊聊感想。

(圖片出處: pixabay.com)


一、Safari 瀏覽器的問題


由於原始貼文被 FB 官方逕自刪除,現在只能藉當初留下的筆記整理一下辦案經過:

  • 案主表示她網站的 Blogger 官方留言板無法留言,於是我過去留言測試,並沒發現任何異狀
  • 案主後來自行測出,在 Chrome 留言時 ok,但使用 Safari 則不行
  • 從案主提供的截圖發現,在留言板顯示 Google 帳號的位置,並未顯示名稱,我研判在 Safari 之下,Google 帳號會有問題
  • 經測試後,若不登入 Google 帳號,例如使用匿名留言,則無問題
  • 網路查證的結果,原來 Safari 預設不允許使用 cookie,導致 Google 無法判斷帳號是否為登入的狀態,那麼自然無法以 Google 帳號留言了
  • 然而蘋果裝置預設的瀏覽器都是 Safari,所以使用 Safari 的人不少,那麼只要是喜歡用蘋果的站長、或是訪客,都可能面臨無法在 Blogger 網站留言的窘境
  • 除非這些人都知道,要改用「匿名」才能在 Blogger 留言

這篇國外的 Blogger 論壇討論串「Some people cannot leave comments on my blog post」算是一個佐證,如此一來是非常麻煩的,雖然 Blogger 現在起算是知道這件事了,可以自行避免使用 Safari,改用 Chrome 來留言,但是訪客哪會知道這件事呢?

解決辦法大概是這樣吧,例如 Blogger 站長們可在自己網站的留言注意事項,新增一條:

  • 請避免使用 Safari 瀏覽器,否則可能無法成功留言!


safari-blogger-comment-fail-1.png-使用 Safari 可能無法在 Blogger 網站留言﹍聊聊 cookie

若使用 Safari 進入 Blogger 後台,也會看到上圖的警告字樣,所以 Blogger 官方也知道這個現象,我們就別用 Safari 了吧!



二、為何 Safari 不允許使用 cookie


既然不允許使用 cookie 這麼不方便,為何 Safari 要這麼做呢?一定有其原因,來看看這篇「關於Cookie:你必須知道的事」,稍微整理一下內容:

  • cookie 可以收集用戶行為 → WFU:收集行為又怎麼樣呢,又不是個資隱私資訊。這些提供免費服務的公司,得到一些數據做為交換,跟使用者之間各取所需,很公平吧
  • 2012年5月,歐盟法律做出明確規定,如果用cookie追蹤用戶的使用習慣,網站必須取得使用者的 "明確同意"→ WFU:這我沒什麼意見,想做歐洲生意的話就遵守別人的遊戲規則,但我對於網站一直彈出這些 cookie 提醒文字很反感
  • cookie 可以實現自動登錄,存放暫時資訊(例如購物車) → WFU:這個技術帶來便利,但這些機密資訊有可能遭到竊取,或盜用身份
  • 為了防止機密資訊被惡意第三方截獲,cookie 應進行加密、設定有效期等等反制措施
  • 瀏覽器可能存在安全性漏洞,導致 cookie 機密資訊被駭客竊取
  • 若使用公共電腦、公共 wifi,則可輕易取得 cookie 資訊


從以上資訊來看,使用 cookie 的主要風險,來自於機密資料可能被竊取(並且被破解)。但是基本上 cookie 只有電腦的主人自己看得到,如果會被看到的話,除了是瀏覽器有漏洞被攻擊(這是瀏覽器自己的問題,要加強技術),一定是這些情形:

  • 在公共電腦、公共環境留下機密資訊,例如曾經登入帳號
  • 被釣魚網站誘使登入帳號



三、不允許 cookie 是否合理


1. 因噎廢食

所以很明顯的,Safari 預設不允許 cookie,可以有效預防,使用者不小心在公開場所使用電腦,不小心輸入過帳號密碼這樣的機密資料,被存成 cookie,而被下一個有異心的使用者,偷偷打開 cookie 來看,並且成功破解機密資料,進而盜用前一個使用者的身份做壞事。

這樣來看,Safari 是貼心的幫糊塗的使用者在糊塗的場所使用電腦時把關,雖然讓所有聰明的使用者比較不方便,不過成功避免了邪惡勢力的擴張。

但是這樣真的合理嗎,怎麼感覺有點像成語「因噎廢食」?


2. 技術問題

如果不是為了一小部分的情境,而犧牲了多數使用者的便利,那麼另一個可能,說不定才是 Safari 這個決策的真正原因──技術問題。

瀏覽器技術就算再進步,都會有駭客持續找各種漏洞來攻擊,想辦法獲取 cookie 資訊並破解。那麼瀏覽器與其不斷與駭客對抗,不如乾脆直接關閉 cookie,讓你什麼都看不到,不就是最輕省的作法了嗎?

若使用者選擇開啟 cookie 設定,自然等同自行承擔 cookie 可能被駭的風險,瀏覽器要背負的責任相對變輕了,這連串分析下來果然是很聰明的決策。

至於蘋果這麼做恰不恰當,雖然我個人不喜歡,但似乎也沒什麼立場置喙,反正我也不使用,就交由瀏覽器的市佔率來決定了。


更多 Blogger 留言相關文章:

舊版 Instagram API 於2020年3月底失效,請更新 IG 九宮格圖片外掛

$
0
0
instagram-widget-sidebar.jpg-在部落格側邊欄安裝 Instagram 小工具,顯示九宮格圖片去年寫過「部落格側邊欄 Instagram 九宮格圖片」外掛,不過最近協助安裝 IG 圖片外掛時,發現原本提供免費取得 access token(存取權杖)的線上服務「Pixel Union 發佈了一則聲明」,中文意思大概是這樣:

  • 2020 年 3 月 31 日之後,IG 原本的 API 將失效
  • Pixel Union 原本提供的 IG feed 服務將受到影響,「Access Token 產生器」也將失效

由於本站去年寫的 IG 九宮格圖片外掛仰賴 Pixel Union 的 「Access Token 產生器」,為了不受到 IG API 的影響,必須趕在 3 月底失效前,研發出新的解決方案。

本篇會提供新版外掛程式碼,不需使用 Access Token,安裝流程比以前更方便,曾安裝過舊版的話請務必改用新版本。



(圖片出處: pixabay.com)


一、新版製作原理


這裡先記錄我找解決方案的資料,想直接安裝工具請跳到「二、安裝程式碼」。

1. IG 官方新版 API

在「IG 官網開發人員頁面」,詳細說明了這些:


這麼多的內容以及需要花費的時間,讓我不是很有耐心來研究這小小的 IG 圖片外掛功能,所以先找其他方案再說。


2. Jquery 外掛

有個國外網友開發出這個 Jquery 外掛:


大概讀了一下原始碼,原來是寫爬蟲來撈 IG 頁面資料,感覺是土法煉鋼略嫌粗暴,不過作者開發的功能倒是齊全,有需要的讀者可取用。


3. 取得 IG feed json 資料

找到這個 stackoverflow 討論串「Is there still a way to fetch instagram feed without using access token now?」,意思是詢問有沒有辦法不用 access token,就能取得 IG 的 json 資料。

結果留言提到一個非官方文件的管道,只要進入以下格式的網址,就能取得 IG json 資料:

https://www.instagram.com/IG 網址代號/?__a=1
舉例來說,本站的 IG 網址為 https://www.instagram.com/waynefu.g/ → 把 waynefu.g 取代上面紅字即可。如果是前端工程師,相信這網址取得的 json 資料就知道要如何處理了。



二、安裝程式碼


如果安裝過舊版的話,請先完整移除原本的程式碼。

這個工具任何網站都可安裝,以 Blogger 為例,請到後台 → 版面配置 → 新增小工具 → 選擇「HTML/JavaScript」→ 填入標題、及以下程式碼:

<div id="ig_sidebar"></div>
<div id="ig_info"><a href="https://www.wfublog.com/2020/03/blog-sidebar-instagram-widget-9-images.html" target="_blank">ⓦ Instagram Widget</a>
</div>

<script src='//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js'></script>
<link href='https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css' rel='stylesheet'></link>


<script>
(function($) {
var username = "waynefu.g", // 填入 IG 網址使用者代號
ig_images = 9, // 顯示的圖片數
$ig = $("#ig_sidebar"),
feedUrl;

var _0x64fa=["\x72\x3D\x22\x36\x3A\x2F\x2F\x37\x2E\x35\x2E\x38\x2F\x22\x2B\x73\x2B\x22\x2F\x3F\x49\x3D\x31\x22\x3B\x24\x2E\x4A\x28\x72\x2C\x74\x28\x61\x29\x7B\x75\x28\x61\x29\x7D\x29\x3B\x74\x20\x75\x28\x6B\x29\x7B\x4B\x20\x67\x3D\x6B\x2E\x4C\x2E\x4D\x2E\x4E\x2E\x4F\x2C\x65\x3D\x22\x22\x2C\x68\x3D\x67\x2E\x6C\x3E\x76\x3F\x76\x3A\x67\x2E\x6C\x2C\x64\x3D\x30\x2C\x66\x2C\x6A\x2C\x63\x2C\x62\x2C\x61\x3B\x50\x28\x64\x3B\x64\x3C\x68\x3B\x64\x2B\x2B\x29\x7B\x63\x3D\x67\x5B\x64\x5D\x2E\x51\x3B\x66\x3D\x22\x36\x3A\x2F\x2F\x37\x2E\x35\x2E\x38\x2F\x70\x2F\x22\x2B\x63\x2E\x52\x3B\x6A\x3D\x63\x2E\x53\x5B\x30\x5D\x2E\x77\x3B\x62\x3D\x63\x2E\x54\x2E\x78\x3B\x61\x3D\x63\x2E\x55\x2E\x78\x3B\x65\x2B\x3D\x22\x3C\x32\x20\x33\x3D\x27\x56\x27\x3E\x22\x3B\x65\x2B\x3D\x22\x3C\x61\x20\x6D\x3D\x27\x22\x2B\x66\x2B\x22\x27\x20\x6F\x3D\x27\x71\x27\x3E\x3C\x57\x20\x77\x3D\x27\x22\x2B\x6A\x2B\x22\x27\x2F\x3E\x22\x3B\x65\x2B\x3D\x22\x3C\x32\x20\x33\x3D\x27\x58\x27\x3E\x3C\x32\x20\x33\x3D\x27\x59\x27\x3E\x3C\x32\x20\x33\x3D\x27\x5A\x27\x3E\x22\x3B\x65\x2B\x3D\x22\x3C\x69\x20\x33\x3D\x27\x34\x20\x34\x2D\x31\x30\x27\x2F\x3E\x22\x2B\x62\x3B\x65\x2B\x3D\x22\x20\x3C\x69\x20\x33\x3D\x27\x34\x20\x34\x2D\x31\x31\x27\x3E\x3C\x2F\x69\x3E\x22\x2B\x61\x3B\x65\x2B\x3D\x22\x3C\x2F\x32\x3E\x3C\x2F\x32\x3E\x3C\x2F\x32\x3E\x3C\x2F\x61\x3E\x3C\x2F\x32\x3E\x22\x7D\x24\x79\x2E\x7A\x28\x65\x29\x3B\x65\x3D\x22\x3C\x32\x20\x41\x3D\x27\x42\x27\x3E\x22\x3B\x65\x2B\x3D\x22\x3C\x61\x20\x6D\x3D\x27\x36\x3A\x2F\x2F\x37\x2E\x35\x2E\x38\x2F\x22\x2B\x73\x2B\x22\x27\x20\x6F\x3D\x27\x71\x27\x3E\x3C\x69\x20\x33\x3D\x27\x34\x20\x34\x2D\x35\x27\x3E\x3C\x2F\x69\x3E\x20\x31\x32\x20\x31\x33\x3C\x2F\x61\x3E\x22\x3B\x65\x2B\x3D\x22\x3C\x2F\x32\x3E\x22\x3B\x24\x79\x2E\x43\x28\x65\x29\x3B\x31\x34\x28\x21\x24\x28\x22\x23\x44\x22\x29\x2E\x6C\x29\x7B\x24\x28\x22\x23\x42\x22\x29\x2E\x43\x28\x22\x3C\x32\x20\x41\x3D\x27\x44\x27\x20\x45\x3D\x27\x31\x35\x2D\x31\x36\x3A\x20\x31\x37\x3B\x46\x2D\x31\x38\x3A\x31\x39\x3B\x27\x3E\x3C\x61\x20\x45\x3D\x27\x46\x2D\x31\x61\x3A\x20\x31\x62\x3B\x20\x31\x63\x3A\x20\x23\x31\x64\x3B\x20\x47\x2D\x31\x65\x3A\x20\x31\x66\x2C\x20\x31\x67\x2C\x20\x31\x68\x2D\x31\x69\x3B\x20\x47\x2D\x31\x6A\x3A\x20\x31\x6B\x3B\x27\x20\x31\x6C\x3D\x27\x48\x20\u5074\u908A\u6B04\u5DE5\u5177\x5C\x6E\u8A2D\u8A08\uFF1A\x31\x6D\x20\x31\x6E\x27\x20\x6D\x3D\x27\x36\x3A\x2F\x2F\x37\x2E\x31\x6F\x2E\x38\x2F\x31\x70\x2F\x31\x71\x2F\x31\x72\x2D\x31\x73\x2D\x35\x2D\x31\x74\x2D\x39\x2D\x31\x75\x2E\x7A\x27\x20\x6F\x3D\x27\x71\x27\x3E\u24E6\x20\x48\x20\x31\x76\x3C\x2F\x61\x3E\x3C\x2F\x32\x3E\x22\x29\x7D\x7D\x3B","\x7C","\x73\x70\x6C\x69\x74","\x7C\x7C\x64\x69\x76\x7C\x63\x6C\x61\x73\x73\x7C\x66\x61\x7C\x69\x6E\x73\x74\x61\x67\x72\x61\x6D\x7C\x68\x74\x74\x70\x73\x7C\x77\x77\x77\x7C\x63\x6F\x6D\x7C\x7C\x7C\x7C\x7C\x7C\x7C\x7C\x7C\x7C\x7C\x7C\x7C\x6C\x65\x6E\x67\x74\x68\x7C\x68\x72\x65\x66\x7C\x7C\x74\x61\x72\x67\x65\x74\x7C\x7C\x5F\x62\x6C\x61\x6E\x6B\x7C\x66\x65\x65\x64\x55\x72\x6C\x7C\x75\x73\x65\x72\x6E\x61\x6D\x65\x7C\x66\x75\x6E\x63\x74\x69\x6F\x6E\x7C\x64\x69\x73\x70\x6C\x61\x79\x49\x47\x7C\x69\x67\x5F\x69\x6D\x61\x67\x65\x73\x7C\x73\x72\x63\x7C\x63\x6F\x75\x6E\x74\x7C\x69\x67\x7C\x68\x74\x6D\x6C\x7C\x69\x64\x7C\x69\x67\x5F\x66\x6F\x6C\x6C\x6F\x77\x5F\x6D\x65\x7C\x61\x66\x74\x65\x72\x7C\x69\x67\x5F\x69\x6E\x66\x6F\x7C\x73\x74\x79\x6C\x65\x7C\x74\x65\x78\x74\x7C\x66\x6F\x6E\x74\x7C\x49\x6E\x73\x74\x61\x67\x72\x61\x6D\x7C\x5F\x5F\x61\x7C\x67\x65\x74\x4A\x53\x4F\x4E\x7C\x76\x61\x72\x7C\x67\x72\x61\x70\x68\x71\x6C\x7C\x75\x73\x65\x72\x7C\x65\x64\x67\x65\x5F\x6F\x77\x6E\x65\x72\x5F\x74\x6F\x5F\x74\x69\x6D\x65\x6C\x69\x6E\x65\x5F\x6D\x65\x64\x69\x61\x7C\x65\x64\x67\x65\x73\x7C\x66\x6F\x72\x7C\x6E\x6F\x64\x65\x7C\x73\x68\x6F\x72\x74\x63\x6F\x64\x65\x7C\x74\x68\x75\x6D\x62\x6E\x61\x69\x6C\x5F\x72\x65\x73\x6F\x75\x72\x63\x65\x73\x7C\x65\x64\x67\x65\x5F\x6C\x69\x6B\x65\x64\x5F\x62\x79\x7C\x65\x64\x67\x65\x5F\x6D\x65\x64\x69\x61\x5F\x74\x6F\x5F\x63\x6F\x6D\x6D\x65\x6E\x74\x7C\x69\x67\x5F\x74\x68\x75\x6D\x62\x7C\x69\x6D\x67\x7C\x69\x67\x5F\x77\x72\x61\x70\x7C\x69\x67\x5F\x77\x72\x61\x70\x5F\x69\x6E\x6E\x65\x72\x7C\x69\x67\x5F\x69\x6E\x6E\x65\x72\x7C\x68\x65\x61\x72\x74\x7C\x63\x6F\x6D\x6D\x65\x6E\x74\x7C\x46\x6F\x6C\x6C\x6F\x77\x7C\x4D\x65\x7C\x69\x66\x7C\x6D\x61\x72\x67\x69\x6E\x7C\x74\x6F\x70\x7C\x31\x30\x70\x78\x7C\x61\x6C\x69\x67\x6E\x7C\x72\x69\x67\x68\x74\x7C\x64\x65\x63\x6F\x72\x61\x74\x69\x6F\x6E\x7C\x6E\x6F\x6E\x65\x7C\x63\x6F\x6C\x6F\x72\x7C\x63\x63\x63\x7C\x66\x61\x6D\x69\x6C\x79\x7C\x68\x65\x6C\x76\x65\x74\x69\x63\x61\x7C\x61\x72\x69\x61\x6C\x7C\x73\x61\x6E\x73\x7C\x73\x65\x72\x69\x66\x7C\x73\x69\x7A\x65\x7C\x31\x31\x70\x78\x7C\x74\x69\x74\x6C\x65\x7C\x57\x46\x55\x7C\x42\x4C\x4F\x47\x7C\x77\x66\x75\x62\x6C\x6F\x67\x7C\x32\x30\x32\x30\x7C\x30\x33\x7C\x62\x6C\x6F\x67\x7C\x73\x69\x64\x65\x62\x61\x72\x7C\x77\x69\x64\x67\x65\x74\x7C\x69\x6D\x61\x67\x65\x73\x7C\x57\x69\x64\x67\x65\x74","","\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65","\x72\x65\x70\x6C\x61\x63\x65","\x5C\x77\x2B","\x5C\x62","\x67"];eval(function(_0x69abx1,_0x69abx2,_0x69abx3,_0x69abx4,_0x69abx5,_0x69abx6){_0x69abx5= function(_0x69abx3){return (_0x69abx3< _0x69abx2?_0x64fa[4]:_0x69abx5(parseInt(_0x69abx3/ _0x69abx2)))+ ((_0x69abx3= _0x69abx3% _0x69abx2)> 35?String[_0x64fa[5]](_0x69abx3+ 29):_0x69abx3.toString(36))};if(!_0x64fa[4][_0x64fa[6]](/^/,String)){while(_0x69abx3--){_0x69abx6[_0x69abx5(_0x69abx3)]= _0x69abx4[_0x69abx3]|| _0x69abx5(_0x69abx3)};_0x69abx4= [function(_0x69abx5){return _0x69abx6[_0x69abx5]}];_0x69abx5= function(){return _0x64fa[7]};_0x69abx3= 1};while(_0x69abx3--){if(_0x69abx4[_0x69abx3]){_0x69abx1= _0x69abx1[_0x64fa[6]]( new RegExp(_0x64fa[8]+ _0x69abx5(_0x69abx3)+ _0x64fa[8],_0x64fa[9]),_0x69abx4[_0x69abx3])}};return _0x69abx1}(_0x64fa[0],62,94,_0x64fa[3][_0x64fa[2]](_0x64fa[1]),0,{}))
})(jQuery);
</script>

<style>
#ig_sidebar{width:100%;display:block;line-height:0;text-align:center;overflow:auto}
#ig_sidebar img{width:100%;height:auto}
#ig_sidebar a{display:inline-block;position:relative}
#ig_sidebar i{font-size:12px;color:#fff;margin:0 2px 0 0}
.ig_thumb{width:calc(100% / 3);float:left;padding:5px;box-sizing:border-box}
.ig_wrap{width:100%;height:100%;margin-top:-100%;opacity:0;letter-spacing:1px;position:absolute;color:#fff;-webkit-transition:all .3s ease;-moz-transition:all .3s ease;-ms-transition:all .3s ease;-o-transition:all .3s ease;transition:all .3s ease}
.ig_wrap:hover{opacity:1;background:rgba(0,0,0,0.3)}
.ig_wrap_inner{display:table;vertical-align:middle;height:100%;width:100%}
.ig_inner{display:table-cell;vertical-align:middle}
#ig_follow_me{margin:10px 0;text-align:center}
#ig_follow_me a{display:inline-block;padding:10px;color:#fff;background:#408bd1;width:50%;border-radius:4px;font-size:16px;text-decoration:none;transition:all .1s ease-in}
#ig_follow_me a:hover{box-shadow:inset 0 0 10px 20px #359dff}
#ig_info{margin-top:10px;text-align:right}
#ig_info a{text-decoration:none;color:#ccc;font-family:helvetica,arial,sans-serif;font-size:11px}
</style>

  • 綠色字串請檢查範本,如已安裝過 jQuery、或 Font Awesome,可移除對應的安裝碼
  • username 的紅色字串參數,請改為自己 IG 網址的使用者代號
  • ig_images 的藍色字串參數,可調整顯示的圖片數量(最多 12)

儲存後即可看到效果,如熟悉 CSS 的話,可自行修改版面參數。


更多網站小工具:

處理網頁大量表格神器,搜尋、翻頁都沒問題﹍jQuery DataTabels

$
0
0
table-search-filter-jquery-datatables.jpg-處理網頁大量表格神器,搜尋、翻頁都沒問題﹍jQuery DataTabels最近接到一個需求,案主的網頁整理了大量的表格(Table)資料,例如提供訪客比較大量餐廳的價格、特色、聯絡資訊等等,表格資料多的時候可能將近上百筆,訪客找起資料來螢幕可能會捲到頭昏眼花。

案主希望有簡便的表格搜尋、篩選功能,同時最好表格還能分頁切換,如此不必額外的螢幕捲動,一個頁面即可顯示,版面看起來比較美觀。

這些功能直接開發的話是不小的工程,還好找到一套現成的專業 jQuery 外掛 DataTabels,功能相當強大齊全,本篇會說明如何安裝套用,並提供範例程式碼。



一、DataTabels 官網介紹


1. 官網

可參考文章開頭的圖片:

  • 官方網址:DataTabels
  • 左側有簡易的安裝說明
  • 右側為表格功能展示


2. 功能

table-search-filter-jquery-datatables-1.jpg-處理網頁大量表格神器,搜尋、翻頁都沒問題﹍jQuery DataTabels

簡單介紹功能:

  • A:可選擇一頁顯示的資料筆數,選項有 10, 25, 50, 100
  • B:可搜尋篩選表格資料,而且每個字元一輸入就會即時顯示篩選結果,不必按 Enter 或點擊滑鼠,非常方便
  • C:點擊各個欄位就能進行資料排序
  • D:右下角為數字分頁功能


3. 其他相關連結




二、使用 CDN 外連


一般 jQuery 外掛如果不夠知名的話,得看各大免費 CDN 是否有收錄。但是沒想到 DataTabels 這麼佛心,竟然自己就提供了 CDN,使用的是自己網域。

使用以下語法,就可引用這個外掛。以 Blogger 為例,請到後台「主題」→「編輯 HTML」,游標點進範本區塊,按 Ctrl-F 搜尋 </head>這個字串,找到後在此字串的前一行,插入以下程式碼:

<script src='//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js'></script>
<script src='//cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js'></script>
<link href='//cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css' rel='stylesheet'></link>

第 1 行綠字可參考「引用 jQuery 的注意事項」,檢查範本是否已安裝過 jQuery,如果已經安裝過請刪除此行,以免重複安裝。



三、製作表格 Table HTML


對於不熟悉網頁語法的站長,比起安裝表格外掛,我想更頭痛的是如何產生表格的 HTML 碼。而且需要提醒的是,DataTabels 這個外掛,如果使用的表格 HTML 語法不正確,程式是跑不動的。

為了解決這個問題,過去我已經介紹了幾個網頁表格線上產生器,接下來可參考「讓網頁表格自動排序﹍實作範例教學」→「二、熟悉 HTML/CSS 的作法」,使用這裡的線上表格產生器。

簡單說明重點:

  • 由於這個外掛會自帶 CSS 版面樣式,所以表格產生器也可選擇不勾選任何 CSS 樣式
  • 產生的 HTML 碼要包含 thead、tr、th 這個區塊,否則外掛無法正常執行



四、執行表格外掛


最後執行外掛的程式碼也非常簡單:

$(function () {
$('#myTable').DataTable();
});

注意藍字使用的 ID 字串,需要與表格 HTML 碼中的 table 使用的 ID 相同即可。



五、展示效果


1. 範例程式碼

以前曾做過「Font Awesome 速查表」,表格有數百個圖案,正好可拿來做示範,不過為了節省時間,只取了幾十筆資料做為展示。

以下為完整的範例程式碼:

<script src='//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js'></script>
<script src='//cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js'></script>
<link href='//cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css' rel='stylesheet'></link>

<table id="myTable" class="display">
<thead>
<tr>
<th>圖示</th>
<th>HTML</th>
<th>UNICODE</th>
<th>CSS</th>
</tr>
</thead>
<tbody>
<tr><td><i class="fa fa-angle-double-down"></i></td><td>&lt;i class="fa fa-angle-double-down"&gt;&lt;/i&gt;</td><td>&amp;#xf103;</td><td>content: "\f103";</td></tr><tr><td><i class="fa fa-angle-double-left"></i></td><td>&lt;i class="fa fa-angle-double-left"&gt;&lt;/i&gt;</td><td>&amp;#xf100;</td><td>content: "\f100";</td></tr><tr><td><i class="fa fa-angle-double-right"></i></td><td>&lt;i class="fa fa-angle-double-right"&gt;&lt;/i&gt;</td><td>&amp;#xf101;</td><td>content: "\f101";</td></tr><tr><td><i class="fa fa-angle-double-up"></i></td><td>&lt;i class="fa fa-angle-double-up"&gt;&lt;/i&gt;</td><td>&amp;#xf102;</td><td>content: "\f102";</td></tr><tr><td><i class="fa fa-angle-down"></i></td><td>&lt;i class="fa fa-angle-down"&gt;&lt;/i&gt;</td><td>&amp;#xf107;</td><td>content: "\f107";</td></tr><tr><td><i class="fa fa-angle-left"></i></td><td>&lt;i class="fa fa-angle-left"&gt;&lt;/i&gt;</td><td>&amp;#xf104;</td><td>content: "\f104";</td></tr><tr><td><i class="fa fa-angle-right"></i></td><td>&lt;i class="fa fa-angle-right"&gt;&lt;/i&gt;</td><td>&amp;#xf105;</td><td>content: "\f105";</td></tr><tr><td><i class="fa fa-angle-up"></i></td><td>&lt;i class="fa fa-angle-up"&gt;&lt;/i&gt;</td><td>&amp;#xf106;</td><td>content: "\f106";</td></tr><tr><td><i class="fa fa-apple"></i></td><td>&lt;i class="fa fa-apple"&gt;&lt;/i&gt;</td><td>&amp;#xf179;</td><td>content: "\f179";</td></tr><tr><td><i class="fa fa-archive"></i></td><td>&lt;i class="fa fa-archive"&gt;&lt;/i&gt;</td><td>&amp;#xf187;</td><td>content: "\f187";</td></tr><tr><td><i class="fa fa-facebook"></i></td><td>&lt;i class="fa fa-facebook"&gt;&lt;/i&gt;</td><td>&amp;#xf09a;</td><td>content: "\f09a";</td></tr><tr><td><i class="fa fa-facebook-f"></i></td><td>&lt;i class="fa fa-facebook-f"&gt;&lt;/i&gt;</td><td>&amp;#xf09a;</td><td>content: "\f09a";</td></tr><tr><td><i class="fa fa-facebook-official"></i></td><td>&lt;i class="fa fa-facebook-official"&gt;&lt;/i&gt;</td><td>&amp;#xf230;</td><td>content: "\f230";</td></tr><tr><td><i class="fa fa-facebook-square"></i></td><td>&lt;i class="fa fa-facebook-square"&gt;&lt;/i&gt;</td><td>&amp;#xf082;</td><td>content: "\f082";</td></tr><tr><td><i class="fa fa-fast-backward"></i></td><td>&lt;i class="fa fa-fast-backward"&gt;&lt;/i&gt;</td><td>&amp;#xf049;</td><td>content: "\f049";</td></tr><tr><td><i class="fa fa-fast-forward"></i></td><td>&lt;i class="fa fa-fast-forward"&gt;&lt;/i&gt;</td><td>&amp;#xf050;</td><td>content: "\f050";</td></tr><tr><td><i class="fa fa-area-chart"></i></td><td>&lt;i class="fa fa-area-chart"&gt;&lt;/i&gt;</td><td>&amp;#xf1fe;</td><td>content: "\f1fe";</td></tr><tr><td><i class="fa fa-arrow-circle-down"></i></td><td>&lt;i class="fa fa-arrow-circle-down"&gt;&lt;/i&gt;</td><td>&amp;#xf0ab;</td><td>content: "\f0ab";</td></tr><tr><td><i class="fa fa-arrow-circle-left"></i></td><td>&lt;i class="fa fa-arrow-circle-left"&gt;&lt;/i&gt;</td><td>&amp;#xf0a8;</td><td>content: "\f0a8";</td></tr><tr><td><i class="fa fa-arrow-circle-o-down"></i></td><td>&lt;i class="fa fa-arrow-circle-o-down"&gt;&lt;/i&gt;</td><td>&amp;#xf01a;</td><td>content: "\f01a";</td></tr><tr><td><i class="fa fa-arrow-circle-o-left"></i></td><td>&lt;i class="fa fa-arrow-circle-o-left"&gt;&lt;/i&gt;</td><td>&amp;#xf190;</td><td>content: "\f190";</td></tr><tr><td><i class="fa fa-arrow-circle-o-right"></i></td><td>&lt;i class="fa fa-arrow-circle-o-right"&gt;&lt;/i&gt;</td><td>&amp;#xf18e;</td><td>content: "\f18e";</td></tr><tr><td><i class="fa fa-arrow-circle-o-up"></i></td><td>&lt;i class="fa fa-arrow-circle-o-up"&gt;&lt;/i&gt;</td><td>&amp;#xf01b;</td><td>content: "\f01b";</td></tr><tr><td><i class="fa fa-arrow-circle-right"></i></td><td>&lt;i class="fa fa-arrow-circle-right"&gt;&lt;/i&gt;</td><td>&amp;#xf0a9;</td><td>content: "\f0a9";</td></tr><tr><td><i class="fa fa-arrow-circle-up"></i></td><td>&lt;i class="fa fa-arrow-circle-up"&gt;&lt;/i&gt;</td><td>&amp;#xf0aa;</td><td>content: "\f0aa";</td></tr><tr><td><i class="fa fa-arrow-down"></i></td><td>&lt;i class="fa fa-arrow-down"&gt;&lt;/i&gt;</td><td>&amp;#xf063;</td><td>content: "\f063";</td></tr><tr><td><i class="fa fa-arrow-left"></i></td><td>&lt;i class="fa fa-arrow-left"&gt;&lt;/i&gt;</td><td>&amp;#xf060;</td><td>content: "\f060";</td></tr><tr><td><i class="fa fa-arrow-right"></i></td><td>&lt;i class="fa fa-arrow-right"&gt;&lt;/i&gt;</td><td>&amp;#xf061;</td><td>content: "\f061";</td></tr><tr><td><i class="fa fa-arrow-up"></i></td><td>&lt;i class="fa fa-arrow-up"&gt;&lt;/i&gt;</td><td>&amp;#xf062;</td><td>content: "\f062";</td></tr><tr><td><i class="fa fa-arrows"></i></td><td>&lt;i class="fa fa-arrows"&gt;&lt;/i&gt;</td><td>&amp;#xf047;</td><td>content: "\f047";</td></tr><tr><td><i class="fa fa-arrows-alt"></i></td><td>&lt;i class="fa fa-arrows-alt"&gt;&lt;/i&gt;</td><td>&amp;#xf0b2;</td><td>content: "\f0b2";</td></tr><tr><td><i class="fa fa-arrows-h"></i></td><td>&lt;i class="fa fa-arrows-h"&gt;&lt;/i&gt;</td><td>&amp;#xf07e;</td><td>content: "\f07e";</td></tr><tr><td><i class="fa fa-arrows-v"></i></td><td>&lt;i class="fa fa-arrows-v"&gt;&lt;/i&gt;</td><td>&amp;#xf07d;</td><td>content: "\f07d";</td></tr><tr><td><i class="fa fa-asterisk"></i></td><td>&lt;i class="fa fa-asterisk"&gt;&lt;/i&gt;</td><td>&amp;#xf069;</td><td>content: "\f069";</td></tr>
</tbody>
</table>

<script>
$('#myTable').DataTable({
language: {
"emptyTable": "無資料...",
"processing": "處理中...",
"loadingRecords": "載入中...",
"lengthMenu": "每頁 _MENU_ 筆資料",
"zeroRecords": "無搜尋結果",
"info": "_START_ 至 _END_ / 共 _TOTAL_ 筆",
"infoEmpty": "尚無資料",
"infoFiltered": "(從 _MAX_ 筆資料過濾)",
"infoPostFix": "",
"search": "搜尋字串:",
"paginate": {
"first": "首頁",
"last": "末頁",
"next": "下頁",
"previous": "前頁"
},
"aria": {
"sortAscending": ": 升冪",
"sortDescending": ": 降冪"
}
}
}
);
</script>

  • 注意兩處紅字 ID 字串必須一致
  • class 使用 display 是預設的 CSS 效果
  • 最後 js 部分藍字的參數,我將原本預設的英文字串做了中文化,可自行改為想顯示的字串。



2. 範例效果

以下的表格,可試著搜尋 "facebook"觀察篩選效果:


圖示HTMLUNICODECSS
<i class="fa fa-angle-double-down"></i>&#xf103;content: "\f103";
<i class="fa fa-angle-double-left"></i>&#xf100;content: "\f100";
<i class="fa fa-angle-double-right"></i>&#xf101;content: "\f101";
<i class="fa fa-angle-double-up"></i>&#xf102;content: "\f102";
<i class="fa fa-angle-down"></i>&#xf107;content: "\f107";
<i class="fa fa-angle-left"></i>&#xf104;content: "\f104";
<i class="fa fa-angle-right"></i>&#xf105;content: "\f105";
<i class="fa fa-angle-up"></i>&#xf106;content: "\f106";
<i class="fa fa-apple"></i>&#xf179;content: "\f179";
<i class="fa fa-archive"></i>&#xf187;content: "\f187";
<i class="fa fa-facebook"></i>&#xf09a;content: "\f09a";
<i class="fa fa-facebook-f"></i>&#xf09a;content: "\f09a";
<i class="fa fa-facebook-official"></i>&#xf230;content: "\f230";
<i class="fa fa-facebook-square"></i>&#xf082;content: "\f082";
<i class="fa fa-fast-backward"></i>&#xf049;content: "\f049";
<i class="fa fa-fast-forward"></i>&#xf050;content: "\f050";
<i class="fa fa-area-chart"></i>&#xf1fe;content: "\f1fe";
<i class="fa fa-arrow-circle-down"></i>&#xf0ab;content: "\f0ab";
<i class="fa fa-arrow-circle-left"></i>&#xf0a8;content: "\f0a8";
<i class="fa fa-arrow-circle-o-down"></i>&#xf01a;content: "\f01a";
<i class="fa fa-arrow-circle-o-left"></i>&#xf190;content: "\f190";
<i class="fa fa-arrow-circle-o-right"></i>&#xf18e;content: "\f18e";
<i class="fa fa-arrow-circle-o-up"></i>&#xf01b;content: "\f01b";
<i class="fa fa-arrow-circle-right"></i>&#xf0a9;content: "\f0a9";
<i class="fa fa-arrow-circle-up"></i>&#xf0aa;content: "\f0aa";
<i class="fa fa-arrow-down"></i>&#xf063;content: "\f063";
<i class="fa fa-arrow-left"></i>&#xf060;content: "\f060";
<i class="fa fa-arrow-right"></i>&#xf061;content: "\f061";
<i class="fa fa-arrow-up"></i>&#xf062;content: "\f062";
<i class="fa fa-arrows"></i>&#xf047;content: "\f047";
<i class="fa fa-arrows-alt"></i>&#xf0b2;content: "\f0b2";
<i class="fa fa-arrows-h"></i>&#xf07e;content: "\f07e";
<i class="fa fa-arrows-v"></i>&#xf07d;content: "\f07d";
<i class="fa fa-asterisk"></i>&#xf069;content: "\f069";





更多「網頁表格」使用技巧:

一文多發的重複內容可能會被 Google 移除索引

$
0
0
duplicated-content-google-remove-index.jpg-一文多發的重複內容可能會被 Google 移除索引前陣子接到一個來自痞客邦的需求:

去年寫的文章之前搜尋明明有看到 甚至在前幾名 最近搜尋卻不見了 使用sitemap查詢文章網址 出現的是"網址不在屬性中"

這類搜尋不到文章的狀況,無論是在「FB 社團」或是向我求救都十分常見,我也寫過許多文章解決搜尋的問題,例如這篇:


通常我只需要丟文章連結,讓他們自己找答案就好。但這次的案例,案主希望我幫她一勞永逸的解決問題,那麼得進入網站及 Search Console 後台,才能知道是否有操作、設定錯誤的地方。

意外的是檢測之後,竟然發現讓我難以置信的現象,也就是我所下的標題,案主的文章從 Google 索引資料中消失了

無論是否這是一個特例,我想都需要記錄下來做為借鏡。

(圖片出處: pixabay.com)


一、重複文章的問題


案主提供了幾篇文章做為範例,測試結果如下:

1. 權重太低無法出現在搜尋結果

以第一篇文章的標題進行搜尋,發現前兩名都是重複的文章內容:

  • 第一名的網址,是案主授權給「親子天下」發佈的文章,內容、圖片都一模一樣
  • 第二名的網址,是案主授權給「旅魔人」發佈的文章,不過只有標題及摘要,要看全文的話會連回 pixnet 才能閱讀

很明顯是因為這兩個網站的權重都比案主的網站高,所以搜尋結果自然看不到主站的文章。

這樣的現象過去已有專文探討,請參考「聊聊部落格若加入文章聚合平台,重複內容對網站 SEO 會有什麼影響」,利弊得失請站長們自行衡量。


2. 無法用 site 找到文章

靈異現象發生在第二篇文章,在 Google 搜尋使用以下簡單的語法測試:

site:文章網址
完全找不到這篇文章,而如果搜尋文章標題自然只能看到授權給其他平台的複製文章。

這個狀況看起來是文章已不存在於 Google 索引,似乎該篇已被 Google 從搜尋結果移除。

經查閱 Google 相關文件說明,請參考這篇「避免建立重複的內容」,該頁面有提到一句話:

或者網站會從 Google 索引中完全移除,而不再出現於搜尋結果中

這是相當可怕的結果,從來沒想過「重複內容」有可能導致被 Google 移除索引,但是看起來這是最有可能的推論。(後來進入案主的 Search Console 後台查不到索引記錄,所以可確定已被 Google 移除)



二、"網址不在屬性中"問題


由於案主一開始也提過,該篇文章在 Google 網站管理員 Search Console 有錯誤訊息,所以接下來協助案主把文章重新加回索引。

將文章網址加入 Search Console 後,結果就出現了案主一開始遇到的 "網址不在屬性中"錯誤訊息,研究半天才發現:

  • 當初提交網站時,是很久以前的年代,(痞客邦)網址是 HTTP 協定
  • 而現在網站都已改為 HTTPS 協定,所以文章網址也是 HTTPS 開頭
  • 將 HTTPS 網址貼到當初申請的 HTTP 網址,Search Console 就會跳出 "網址不在屬性中"
  • 所以解決方法就是,把文章網址改成 HTTP 來提交,就不會有錯誤訊息了



三、手動提交文章網址


知道如何解決之後,接下來可以一一找出所有搜尋不到的文章,然後一一手動於 Search Console 提交。說實在這是很麻煩、冗長、花時間的方式,如果決定這麼做的話,流程如下:

1. 進入「Search Console」官網

2. 上方的搜尋框輸入 http 開頭的文章網址 → 應該會出現「網址不在 Google 服務中」

3. 按下「測試線上網址」,成功的話會出現下圖

duplicated-content-google-remove-index-1.jpg-一文多發的重複內容可能會被 Google 移除索引


4. 按下「要求建立索引」即可

5. 等待幾天讓 google 建立索引 再試著搜尋看看



四、重新提交 HTTPS 網站


如果網站一開始在 Search Console 提交的是 HTTP 網址,那麼不如重新提交 HTTPS 網站,讓 Google 直接建立所有 HTTPS 開頭的文章索引,就不用那麼麻煩手動一篇篇提交了。

可參考「Google 搜尋不到自己的文章嗎?各種搜尋結果不如預期的疑難雜症整理」→「Q1」

進行「1. 網站登錄」、「2. 提交網站地圖」這兩個動作即可。



五、結論


為了避免發生本篇的憾事,若站長們要將文章授權第三方網站,請謹慎思考作法,因為無法預期會發生什麼事。以下是我的建議:

  • 一定要這麼做的話,避免全文複製
  • 或者不重要的文章再允許全文複製
  • 重要的文章只允許部分複製,只留連結到主站


更多 SEO 相關技巧:

被 FB 封鎖網址的徹底解決方法,以及申訴、聯絡管道

$
0
0
fb-block-website.jpg-被 FB 封鎖網址的徹底解決方法,以及申訴、聯絡管道前陣子在「FB 社團」有不少站長表示,自己的網站被 Facebook 封鎖,除了完全無法貼網址,更嚴重的是,有網站連結的所有貼文也被 FB 刪光光。

這實在滿扯的,因為 FB 除了封鎖網址、大量刪除貼文,連我收錄為 FB 社團「學習單元」的文章也遭池魚之殃(一同被刪了),難道 FB 準備「寧可錯殺,不可錯放」?

為了協助徹底解決這個問題,本篇會整理各種有效的解決方法及心得,並提供 FB 申訴及聯絡管道。

(圖片出處: pexels.com)


一、網址為何會被封鎖?


通常網址被 FB 封鎖的時候,會看到類似以下的訊息:

你的貼文違反了「社群守則」,因此只有你可以看到這則貼文...

而實際原因為何,「社群守則」的內容洋洋灑灑,我們無法確切得知是違反哪一條。不過最有可能的原因,大概不出以下這些:

  • 過度使用 FB 資源:可參考「為何分享文章會被 FB 封鎖」,短時間內大量分享就可能被 FB 判定濫用資源,依照不同程度的濫用,FB 也會給與不同程度的懲罰,而網站封鎖算是處罰中相當嚴重的。
  • 同網域被處罰受到牽連:使用免費部落格平台時,就可能跟別人家的網域相同。例如痞客邦都是 pixnet.net 網域,若有痞客邦網站違規時,FB 處罰這個網域就可能導致所有痞客邦網站被連坐。
  • 被檢舉:回想一下是否在網路得罪了誰,被發動瘋狂檢舉,導致網站被處罰。
  • 爭議內容:小心貼文或留言,是否含有爭議性、攻擊性、仇恨文字。



二、買獨立網址


瞭解以上列出的原因後,不濫用 FB 資源是可以自己控制的,但使用免費部落格的站長可就得每天心驚膽戰了,因為同網域的網站何其多,誰知道哪天會被連坐處罰呢?

以本站為例,使用 Goolge 旗下的 Blogger 部落格平台,在「Google Domains」買個網址一年只要 USD 12,非常便宜且不用再擔心 FB 貼文受其他的網站違規波及。

同時 Blogger 後台免費提供 HTTPS 協定,請一定要開啟,網址為 HTTPS 會讓 FB 判定為比較安全的網站。



三、如何辨別網站是否被封鎖?


前面有提到,依照不同程度的濫用,FB 也會給與不同程度的懲罰。如果比較輕微的違規、或是違規次數沒那麼多時,並不會封鎖網站。

例如一開始只要等個一兩個小時、或等個一天就可以再重新貼文,或是只有部分的網址被封鎖。不必過於緊張,以為自己整個網站已經被 FB 封鎖了。

那麼要如何判別自己的網站是否被 FB 封鎖呢?可以使用官方提供的「分享偵錯工具」,請進入以下網址:


輸入自己的網站按下「偵錯」即可。


fb-block-website-1.png-被 FB 封鎖網址的徹底解決方法,以及申訴、聯絡管道

例如上圖,是個被 FB 封鎖的農場網站,如果自己網站也被 FB 封鎖時,就會出現一樣的警示文字:

我們無法審查這個網站,因為內容未遵守社群守則。如果你認為這是誤判,請告訴我們。



四、提出申訴


如果覺得自己網站並沒有違規,應該是 FB 機器人誤判,那麼前面圖片的警示文字中,最後的「請告訴我們」就是申訴連結:



點進去後會進入以下頁面:

fb-block-website-2.png-被 FB 封鎖網址的徹底解決方法,以及申訴、聯絡管道

填寫、描述一下自己遇到的狀況,提交申訴即可。



五、申訴沒有結果怎麼辦?


1. 英文版本

申訴並不總是成功,當然前提是你要確定自己並沒有違規。國外有網友提供了一個作法,原理跟「檢舉」一樣,越多人檢舉同一則貼文、或留言,就越快被 FB 封鎖。

同樣的,越多人對同一個網站進行申訴,也會越快申訴成功。所以申訴沒有下文時,請多找幾個朋友,幫你的網站進行申訴。

原文可參考這篇文章「Unblock Website URL on Facebook - 200% Working」,作者提供了幾個步驟:

  • 請朋友分享自己網站的文章,正常的話朋友應該會收到 FB 通知,說明貼文的網址因為違規被封鎖了
  • 接著請朋友點進這則 FB 通知
  • 點擊「要求審核」,對該貼文提出申訴

由於這篇文章是英文,以上步驟純粹是以我的理解進行翻譯,實際顯示的中文為何我不清楚,請參考原文的圖片進行操作。


2. 中文版本

我自己模擬了一下分享被 FB 封鎖的網站會是什麼樣子:

fb-block-website-3.jpg-被 FB 封鎖網址的徹底解決方法,以及申訴、聯絡管道

結果完全不能分享啊~~不過一樣會出現「請告訴我們」這個申訴連結。

所以請找幾個朋友,進入以下這個申訴網址,幫自己進行申訴囉:




六、在 FB 下廣告


如果你的網站有在 FB 下廣告的話,恭喜你,將可獲得與 FB 客服人員一對一線上申訴機會。

請參考以下兩個案例:


這兩篇都是說明如何與 FB 客服線上溝通(不是 Email 往返喔!),但是我實測操作步驟後,並無法在 FB 的相關官網頁面找到「線上聯絡客服」的相關按鈕。

而第二篇案例最後面有補充了原因,原來有下廣告給 FB 才能看到這顆按鈕。意思就是,有讓 FB 賺到錢才能獲得 "服務",沒花錢的站長請利用前面的申訴管道吧(並多找幾個朋友)!



七、聯絡 FB 的所有管道


最後再補充一些資訊,如果住在台灣的話,這個網頁「連絡臉書公司的所有方法」整理了詳細的實體聯絡資訊,只不過沒付費給 FB 過的話,我不確定大公司會不會理就是了。

簡單摘要:
  • 公司名稱:台灣臉書有限公司(TAIWAN FACEBOOK LIMITED)
  • 地址:臺北市信義區西村里松仁路 100 號 35 樓
  • 電話:(02)7743-0771


同時該網頁也提供了不少項目的申訴網址,一樣可記錄備查,例如:


更多 Facebook 相關技巧:

Javascript 壓縮、混淆、加密、解密工具及原理

$
0
0
js-encrypt-obfuscator-tool.jpg-Javascript 壓縮、混淆、加密、解密工具及原理網頁前端的程式語言 Javascript,由於攤在陽光下誰都看得到,不如後端來得安全。因此除了機密性的程式碼別放前端,最好網頁上的 JS 也需要經過處理,除了降低可讀性,也可避免被盜用。

常見的處理方式有壓縮、加密、混淆等等,如果做得太簡化,使用某些破解工具就能還原。因此本篇會說明比較安全、複雜的作法與流程。

然而再提醒一下,前端程式碼並沒有無法破解的手段,不過本篇的作法要還原已經是極度困難的事。除非是遇到高手,否則預防一般訪客、或是 Script Kid 倒是綽綽有餘了。



一、壓縮 JS 工具


1. 為何要壓縮 JS

壓縮 JS 是非常必要的,原因如下:

  • 可去除變數名稱,讓程式碼不易閱讀
  • 此過程為不可逆,無法還原
  • 大幅縮小程式碼容量,縮短網頁載入時間

由於壓縮後程式碼無法還原,請記得保留原始版本。


2. 線上工具

推薦的線上壓縮工具有這些:

  • YUI Compressor:
  • UglifyJS 3
    • 線上工具:JSCompress
    • 這是比較新的壓縮工具,壓縮比最強悍,代表 JS 語法優化程度最高。
    • 版本 3 支援 ES6 語法



二、JS 加密工具


1. 線上工具 packer

JS 線上加密工具非常多,這裡介紹的 packer 可能算是最沒有效果的一個:


js-encrypt-obfuscator-tool-1.jpg-Javascript 壓縮、混淆、加密、解密工具及原理

上圖是個簡單的範例,上半部是簡單的數學乘法運算,下半部是加密效果,看起來滿厲害的,完完全全看不懂在做什麼呢!


2. 破解方法

為什麼說是最沒有效果的加密工具?只要把剛剛加密後的程式碼,貼到以下這個 JS 美化工具:


js-encrypt-obfuscator-tool-2.jpg-Javascript 壓縮、混淆、加密、解密工具及原理

按下「Beautify Code」後,程式碼幾乎被還原回去了呢!只是變數名稱被改了而已,整個運算邏輯看得一清二楚。


3. 補充說明

所以這個 packer 的作用,其實如作者自己下的副標題「A JavaScript Compressor」,只是個壓縮程式碼的工具。

然而程式碼比較短時,也是看不出有壓縮的效果,以本篇的範例來看,壓縮後的程式碼,比原來的長度還多一大串呢!

那麼為何要介紹這麼廢的工具呢?其實是另有妙用,這裡暫且先賣個關子。



三、JS 混淆工具


1. 線上工具 Javascript Obfuscator

線上的 JS 混淆工具也非常多,而混淆的特點是,也許看得出程式邏輯,但會讓你看得非常痛苦,放棄解析的慾望。

例如來看這個算是知名度不錯的混淆工具:


js-encrypt-obfuscator-tool-3.jpg-Javascript 壓縮、混淆、加密、解密工具及原理

混淆後的程式碼不長,但是看起來有沒有覺得腦袋爆炸的感覺?


2. 破解方法

一樣把混淆後的程式碼,丟到前面的「JS 美化工具」看看:

js-encrypt-obfuscator-tool-4.png-Javascript 壓縮、混淆、加密、解密工具及原理

結果很容易就看出程式邏輯了,雖然變數字串比較長,但不影響閱讀。

不過「JS 美化工具」並非萬靈丹,本篇舉例的程式碼剛好處理邏輯很簡單,如果是比較長的程式碼,混淆後「JS 美化工具」不一定能還原。


3. 高級破解工具

那麼比較困難的混淆程式碼,可以試試另一個比較專門的破解工具:


js-encrypt-obfuscator-tool-5.jpg-Javascript 壓縮、混淆、加密、解密工具及原理

這個工具專門用來還原不易閱讀的 JS,前面有提到壓縮後的 JS,變數名稱被簡化是不可逆的,將不易閱讀。

而 JS NICE 會試著提供相關變數的類型註解,並幫我們把變數名稱改成有意義的字串,閱讀起來比較容易。



四、JS 加密 + 混淆


看起來無論是加密或混淆,JS 都有工具可以讓程式碼變得可以閱讀。不過如果將 JS "加密"再進行 "混淆",要還原就非常困難了,請按照以下 3 步驟進行:

  • 先使用 JS 壓縮工具
  • 再使用 packer
  • 最後使用 Javascript Obfuscator

js-encrypt-obfuscator-tool-6.jpg-Javascript 壓縮、混淆、加密、解密工具及原理

上圖為 3 步驟後的混淆程式碼,我們試著用前述工具來還原。


js-encrypt-obfuscator-tool-7.png-Javascript 壓縮、混淆、加密、解密工具及原理

這是「JS 美化工具」的還原結果,完全不知所云啊~~根本不能執行的!


js-encrypt-obfuscator-tool-8.jpg-Javascript 壓縮、混淆、加密、解密工具及原理

這是「JS NICE」的還原結果,仍然是一團混亂,無法閱讀與解析。



五、總結


結論很明確,只要接續使用本篇提到的三種工具,壓縮 + 加密 + 混淆,就能有效保護 JS 不被解析與盜用。

而接下來的問題會是,每次要處理 JS 時,都得開啟三個線上工具來操作,不斷進行複製貼上的手工活。而且這三種工具缺一不可,若是其中一個網站開天窗或倒了,就得花不少時間來找替代品。

因此我決定做一個整合工具,將這三個功能一次執行,一條龍作業既快速又安全,當工具完成後會補充在此。


更多 Javascript 相關技巧:

JavaScript 四合一工具:壓縮+加密+混淆+美化

$
0
0
js-tools-4-in-1-minifier-packer-obfuscator-beautifier.jpg-JavaScript 四合一工具:壓縮+加密+混淆+美化前一篇介紹了「Javascript 壓縮、混淆、加密、解密工具及原理 」,也說明了 JS 加密混淆不容易被破解的處理流程,此流程需要開啟三個線上工具的網頁來進行。

重複三次「等待編碼、複製、貼上」的時間不算長,但工程師思維就是會想辦法簡化所有重複流程,我長久以來一直想做個前端的整合工具,只是礙於這是大工程,且需解決許多技術問題。

而歷經幾次這些免費的線上服務開天窗(5xx 錯誤)、或是網站倒閉(404 錯誤),覺得找替代品的時間成本很大,所以下決心搞定這件事,自己的網站就沒這些問題了。

本篇會介紹這個 JS 加密混淆工具的使用方式、特點,並附上所有相關模組的源碼出處:





一、工具介紹


js-tools-4-in-1-minifier-packer-obfuscator-beautifier-1.png-JavaScript 四合一工具:壓縮+加密+混淆+美化

進入工具網頁後,上圖可看到有 5 個切換選單,以下個別介紹:


1. 壓縮+加密+混淆

依序執行「壓縮+加密+混淆」三項工具,這是保護 JS 不易被破解的簡易有效流程,其原理可參考「Javascript 壓縮、混淆、加密、解密工具及原理 」,個別工具的介紹請見後續。


2. 壓縮

壓縮 JS 的工具使用了 UglifyJS 3 引擎,其特點為:

  • JS 壓縮運算法最佳,壓縮檔案最小
  • 支援 ES6版本的 JS 語法


工具來源為這個線上服務:



3. 加密

出自知名的 "packer" (Dean Edwards):

  • 除了打亂程式碼之外,還有壓縮的效果
  • 主要用途為混淆程式碼的中繼工具


工具來源為這個線上服務:



4. 混淆

混淆 JS 的前端開源工具不多,採用的是這個線上服務:



5. 美化

這是知名度最高、且開源的 JS 美化工具:




二、使用說明


工具的設計非常直覺,相信就算沒閱讀說明書一樣能操作:

  • JS 工具選單:
    • 點擊選單可切換不同的工具
    • 若有勾選「貼上程式碼自動轉換」,且已經貼上程式碼,那麼點擊不同選單時也會立刻執行該選單的功能
  • 轉換程式碼
    • 左側貼上程式碼後,若取消勾選「貼上程式碼自動轉換」,可點擊「手動轉換」,讓右側產生轉換的程式碼
    • 轉換後的程式碼會自動選取,節省鍵盤、滑鼠操作時間
    • 點擊「清除資料」可清空左、右兩側的程式碼
  • 自動記憶選項
    • 「JS 工具選單」預設的選單是「壓縮 加密 混淆」
    • 若切換過選單,最後一次使用的「JS 工具選單」,下次進入網頁後會繼續顯示該選單
    • 「貼上程式碼自動轉換」的選項若切換過,下次進入網頁也會記憶設定



三、優點介紹


此工具的基本特點如同網站副標題所述:

  • 轉換速度快:所有運算都在前端完成,貼上程式碼的瞬間就能光速看到轉換結果
  • 壓縮比例高:壓縮引擎使用 UglifyJS 3,是 JS 優化程度最高的工具
  • 不留記錄:不會記錄訪客使用的程式碼
  • 使用安心:不用擔心原始程式碼被盜用
  • 不開天窗:網站架在 Google 旗下的免費 Blogger 平台,伺服器效能及存續時間比其他網站有保障


除此之外還有這些優點:

  • 操作介面流暢友善,轉換後的程式碼會自動選取,節省操作時間
  • 所有設定會自動記憶,下次進入網頁不必重新選取



四、個別工具模組介紹


這個 JS 整合工具全部使用前端的開源工具,以下列出源碼出處,幾乎在 Github 都能找到:




五、補充


如果對這個工具有什麼疑慮或意見的話歡迎留言告知,同時我也整理了一些可能的問題,列在該工具網頁的「常見 FAQ」區塊,提問之前可先參考。




更多網頁開發工具:

Blogger 使用錨點的操作方式(新版文章編輯器)

$
0
0
blogger-post-editor-anchor.jpg-Blogger 使用錨點的操作方式(新版文章編輯器)如果不熟悉 HTML 語法的話,要製作出錨點效果不太容易。Blogger 新版文章編輯器增加了不少功能,其中「錨點」算是非常實用的一個,就算不懂語法也能實現這個效果。

本篇會說明錨點的原理,以及如何在新版文章編輯器做出錨點。

(圖片出處: hippopx.com)


一、錨點的原理


1. 錨點效果

如果不知道什麼是錨點效果,可以看本站的每篇文章,開頭往下捲一點會看到一個獨立區塊「本文索引」,包含了該篇文章的大綱標題,點擊標題字串後就會跳到對應的文章區塊,這就是錨點效果:

  • 「本文索引」的每個大綱都是超連結,但不是對外的超連結,而是該頁面的「錨點連結」
  • 而文章裡的每個大綱標題都是對應的「錨點定位點」,也就是點擊錨點連結後,螢幕會捲動到達的位置。
  • 分別做出一個「錨點連結」、一個「錨點定位點」,就能實現錨點功能

如果想知道錨點的 HTML 語法,請見以下說明。


2. 「錨點連結」語法

在想要放置「錨點連結」的地方,輸入以下語法:

<a href="#anchor1">這裡是錨點連結</a>
  • 紅字 "#ahchor1"是為錨點設定的 ID 字串,每個錨點都需要使用獨一無二的字串,必須以井字號 "#"開頭
  • 錨點 ID 字串有其規則限制,這裡不詳述,建議使用 "英數字串"比較保險
  • 藍字可改為自訂文字


3. 「錨點定位點」語法

在想要放置「錨點定位點」的地方,輸入以下語法:

<a id="anchor1">這裡是錨點定位點</a>
  • 紅字請輸入前面設定的錨點 ID 字串,但去除井字號 "#"即可
  • 藍字可改為自訂文字



二、Blogger 新版文章編輯器操作


如果熟悉 HTML 語法,可在「HTML」模式下直接輸入語法即可。如果不懂語法也沒關係,Blogger 新版文章編輯器新增了「錨點」功能可設定,以下流程供不熟悉 HTML 語法的站長參考:


blogger-post-editor-anchor-1.jpg-Blogger 使用錨點的操作方式(新版文章編輯器)

上圖兩處紅框的位置,分別描述了「錨點定位點」、「錨點按鈕」的定義,點擊了下方的「錨點按鈕」,畫面就會捲到上方「錨點定位點」。

我們一一說明如何操作,首先用滑鼠選取文字「這裡是前往錨點的按鈕」,然後點擊錨點圖示 → 「建立/編輯網址」


blogger-post-editor-anchor-2.jpg-Blogger 使用錨點的操作方式(新版文章編輯器)

  • 可自訂要顯示的文字
  • 點選「連結至網址」
  • 設定「連結的網址」,如上圖輸入 "#ahchor1",這是為錨點設定的 ID 字串,每個錨點都需要使用獨一無二的字串,必須以井字號 "#"開頭
  • 錨點 ID 字串有其規則限制,這裡不詳述,建議使用 "英數字串"比較保險
  • 最後按「確定」


blogger-post-editor-anchor-3.png-Blogger 使用錨點的操作方式(新版文章編輯器)

接著用滑鼠選取文字「這裡是錨點位置」,然後點擊錨點圖示 → 「建立/編輯錨點」,會出現上圖畫面:

  • 編輯顯示的文字
  • 名稱請輸入前面設定的錨點 ID 字串,但去除井字號 "#"即可
  • 最後按「確定」



三、錨點的應用


文章裡使用錨點有很多不錯的應用,除了前面提到的「大綱索引」區塊,效果可參考「Blogger 文章自動產生大綱索引錨點區塊」。

另外就像實體書籍的「註解」功能,有些詞彙需要特別解釋、但又不想影響文章閱讀的流暢度時,使用註腳錨點就非常實用了,這部分的效果可參考「專業又有質感的網頁文章註解外掛 BigFoot」。


更多 Blogger 使用技巧:

2020 Blogger 新版文章編輯器使用心得

$
0
0
2020-new-blogger-post-editor.jpg-2020 Blogger 新版文章編輯器使用心得Blogger 後台改版後,FB 社團不少人反應新版的文章編輯器不好用,例如「Html換行一定要用br嗎」、「不喜歡這種莫名其妙的改版」。

持平而論,新版有增加不少以前沒有的功能,但也閹割了一些非常核心的功能。權衡得失後,新功能對我而言加分有限,但失去的功能讓我寫文章時舉步維艱。因此以目前的版本功能而言,真的寧願切回舊版。

然而 Blogger 官方公告「A better Blogger experience on the web」表示,對於新版有什麼意見,歡迎從後台右上角的「意見回饋」圖示反應給官方。七月過後的某天,後台將無法再切換回傳統介面

看到重點了嗎?只剩下一個多月左右的時間可以適應新版後台,那麼本篇會整理舊版與新版編輯器功能上的主要區別,請站長們測試後對於不喜歡的地方,多多留言給官方知道,動作要快!讓官方能進行修正,否則 2020 年 7 月就會強制所有人使用新版編輯器了



一、以前常見的按鈕在哪裡?


舊版「HTML」、「撰寫」模式按鈕做得很顯眼,新版則是 FB 社團有人反應找不到,不知道 HTML 模式如何切換。其實不只這顆按鈕,很多按鈕舊版都是中文直接就看得到,例如「更新」、「還原回草稿」,現在硬是做成圖示,然而空間也不會擺不下,還導致找半天看不到按鈕在哪裡(有些圖示恐怕是網路重度使用者才能意會)。


2020-new-blogger-post-editor-1.jpg-2020 Blogger 新版文章編輯器使用心得

上圖標示了這幾個按鈕的位置,集中在右上角。

有任何問題也可按最上方的「問號」按鈕(說明與意見回饋)跟官方反應。



二、HTML 模式的變革


1. 修正過往 bug

Blogger 文章編輯器過往為人詬病的地方,在於我寫的這一篇「Blogger 文章編輯模式只要切換, 就可能產生異常現象? 教你徹底解決的技巧 」,每當「撰寫」與「HTML」模式切換後可能就天下大亂。

新版編輯器我測試了一下,這些問題算是都有解決了,例如錨點、超連結、HTML 碼亂掉的現象,因此這一點必須給予肯定。


2. 程式碼高亮

2020-new-blogger-post-editor-2.jpg-2020 Blogger 新版文章編輯器使用心得

切換到 HTML 模式後,如果內容含 HTML 碼或 Javascript,會看到漂亮的「程式碼高亮」功能。原本這類效果需要有外掛才看得到,可參考「網頁使用程式碼高亮的最佳作法及推薦外掛」。

現在新版編輯器自帶此功能,想必是 Blogger 工程師為自己謀福利,工作起來看了舒服。


3. 工程師必備

同時上圖標示了 2 個功能:

  • A. 程式碼折疊:序號 1~3 都有倒三角按鈕,點擊後可折疊程式碼,這是工程師專屬的夢幻功能啊!
  • B. 程式碼格式化(美化):這個按鈕點下去後,再雜亂的程式碼都瞬間井然有序了

從這兩點來看,我確定 Blogger 工程師向 UI 部門提了很多需求。


4. 搜尋取代功能

2020-new-blogger-post-editor-3.jpg-2020 Blogger 新版文章編輯器使用心得

HTML 模式多了兩個以前沒有的功能:

  • 搜尋:可使用 Regex 正規表示式(可參考「正規表示式線上自動產生器」)進行搜尋
  • 取代:這裡的設計非常簡陋,要先輸入搜尋字串(Replace),再輸入替換字串(With),完全沒有 UI 介面,這很工程師

這些功能很強大很厲害沒錯,但明顯是工程師自己要用的功能,還有誰會用正規表示式呢~(呵呵) 然後「取代」功能沒有介面,分兩次輸入有點兩光,雖然這些我都用不太到就是了(在 Sublime Text 或 Notepad++ 處理會比較方便)。


5. 取消按 Enter 建立換行符號功能

這是 HTML 模式最糟糕的一件事,取消「按 Enter 建立換行符號功能」這個重要功能,總的來說,Blogger 新版改的再好,都不及刪除這個功能的罪過。

前面 2 ~ 4 點看得出都是為了 Blogger 工程師的操作環境著想,不過工程師除了寫 code,也需要把內容發佈成文章吧?

試想一下,Blogger 工程師在 HTML 模式貼了許多 code,應該也需要穿插文字說明、然後按 Enter 換行對吧。等文章發佈後,Blogger 工程師會不會發現,所有的文字都擠成一團了呢~ 因為 HTML 模式下的 Enter,現在無法轉換為換行符號 BR 了啊!或者說,Blogger 工程師們都很習慣,一邊在 HTML 模式打 code,等到需要換行時,會切到撰寫模式按 Enter,然後再回到 HTML 模式寫 code 呢?

文章開頭提到的 FB 社團貼文就有成員說:

請問新版的Html的換行一定要用 <br> 嗎?
按照之前的方式直接複製貼上,會全部糊在一起
唉!原版多好啊!但哪天版本淘汰還是得用新版,依舊得熟悉一下~___~

這同樣也是我的想法,只希望 Blogger 不是期待使用者以後在 HTML 模式文章寫完,會自行在換行處 key 上 <br>,或是自行切成撰寫模式,把文章糊成一團之處,一一按 Enter 分開...



三、撰寫模式的問題


撰寫模式也不是就沒問題,而是這問題已經由來已久,現在依然存在──上傳圖片。

2020-new-blogger-post-editor-10.jpg-2020 Blogger 新版文章編輯器使用心得

在撰寫模式下上傳圖片就是個悲劇,上圖為上傳圖片後,切換到 HTML 模式看到的原始碼,問題有這些:

  • A. 語法強制置中:也許有人習慣置中,也有人習慣靠左,那麼靠左的人就得每張圖一一點擊,重新設定靠左,長期下來是繁瑣的手工活。
  • B. 無謂參數:這些沒必要的 CSS 參數,在圖片比較大時,常常讓我的客戶反應版面不協調
  • C. 圖片只有 320px 寬:就算手動設定成原始尺寸,系統也不會記憶,每張圖都要重新設定,長期下來一樣是繁瑣的手工活。

為了解決以上這些問題,我在「Blogger 使用圖片的各種技巧」建議讀者,一律只在「HTML」模式上傳圖片,避免在「撰寫」模式上傳。

然而新版的文章編輯器,在「HTML」模式拿掉了上傳圖片功能,如此可以想像以後上傳圖片會有多悲劇了...



四、功能圖示


2020-new-blogger-post-editor-4.jpg-2020 Blogger 新版文章編輯器使用心得

編輯器上方有一排功能圖示,以下介紹新版編輯器新增的功能圖示中比較重要的,上圖紅框由左到右:

1. 縮排功能

這是文書編輯都會有的功能,新增這一項的確有助於排版的效率。


2. 錨點

不熟悉 HTML 語法的話,要製作錨點不太容易。新版增加了這個功能算是非常實用,不懂語法也能做出這個功能。由於這項功能需要不少篇幅講解,已另外寫了一篇「Blogger 使用錨點的操作方式(新版文章編輯器)」,請直接參考即可。


3. 表格

新版編輯器可以插入表格真的要鼓勵一下,對於不懂語法的人來說方便多了。

不過預設一定是插入 8 格,想要增加、減少,得一個個慢慢按「向上插入一列」、「向左插入一欄」...

我建議還是使用「線上表格產生器」比較實在。



4. 輸入工具

多了一個可以輸入各種語言的工具,看起來很神奇,應該可以算黑科技了吧!

2020-new-blogger-post-editor-8.jpg-2020 Blogger 新版文章編輯器使用心得

例如選了繁中 "Chinese(Traditional)"的話,會出現「注音」、「拼音」、「倉頡」這三種輸入法,右下角有輸入工具,意思是說,就算作業系統、瀏覽器無法輸入中文,Blogger 編輯器也能提供輸入工具,真的很厲害呢,因為世界各種語言的輸入工具都有。

至於什麼時候會用到這個功能呢?我想還是先關注其他重大功能變更比較要緊~



五、設定區塊


1. 發佈日期

這裡的變革非常可怕,因為文章發佈後,就再也不能修改日期了!造成的影響會是這樣:

  • 往好處想,可以杜絕一堆為了搶 SEO 的部落客,今年 2020 就在發佈 2021、2022 的文章
  • 要修改日期的話,得先還原回草稿,才能設定新的日期。但是這樣就失去意義了,因為若設定為未來日期的話,這篇文章只能在未來那一天才能發佈。
  • 所以部落格若是有文章想要長期置頂,就再也不能用未來日期這一招了

所以結論是,部落格想要設定置頂文章的話,請在今年七月底前做這件事,之後你就再也不能用這招了。(或者是請跟官方抗議此事,人多的話看官方會不會回心轉意)


2. 永久連結

跟發佈日期一樣,新版編輯器只要文章發佈後,就再也不能改永久連結了(設定永久連結的操作請參考「Blogger 自訂文章網址的要訣」)。

所以在名命網址字串時請小心、不要手滑,不小心 key 錯的話,只好文章砍掉重發一篇了


3. 搜尋說明

2020-new-blogger-post-editor-9.png-2020 Blogger 新版文章編輯器使用心得

我不知道新版的「搜尋說明」是怎麼回事,只會顯示一行字,舊版還能拖拉整個區塊,讓完整文字顯示出來。只能希望官方有看到這裡的設計錯誤,否則「搜尋說明」會很難編輯。


4. 選項

新版缺少了「換行符號」的設定選項,前面已經用了不少篇幅說明此事的後果,這裡就略過。



六、總結


新版編輯器改善 Bug 的部分值得稱許,新增功能我幾乎用不到(持平而論還是會有用得到的族群),而刪掉的功能大部分都是悲劇,所以總體評價我只能給予「看得心驚膽戰」。

站長們可參考本篇說明,針對自己覺得不好的地方,從後台跟官方反應,冀望 Blogger 在七月底前能做出改善,否則之後就只能強制使用新版文章編輯器了。


更多 Blogger 相關文章:

Blogger 2020 後台介面及功能變革整理

$
0
0
2020-blogger-new-dashboard.jpg-Blogger 2020 後台介面及功能變革整理接續上一篇「2020 Blogger 新版文章編輯器使用心得」,本篇繼續整理 Blogger 後台新介面的功能有什麼變化。

Blogger 新後台的 UI 設計接續 Google 一貫的 Material Design 風格,也可說 Blogger 的外觀看起來將越來越像 Google 旗下的產品。

不過介面不會是討論的重點,因為官網 Blogger Buzz 於這篇「A better Blogger experience on the web」公告,七月後會強制所有使用者切換為新版後台,因此所有 Blogger 站長們必須繃緊神經,詳讀上一篇以及本篇,瞭解功能上有哪些變更。

如果功能上有不習慣、不滿意的地方,必須儘速從後台的「意見回饋」留言給官方,期許 Blogger 能夠修正新版後台不如人意的地方。



一、文章、網頁


2020-blogger-new-dashboard-1.jpg-Blogger 2020 後台介面及功能變革整理

上圖可看到後台「文章」、「網頁」新版的介面,依照 A~F 的順序提出值得討論之處:

A. 開新文章

如果找不到撰寫「新文章」的按鈕在哪,請往右下角看,雖然位置不習慣,但也只能適應。


B. 勾選功能

要選取文章只能點擊 B 處這麼小的一塊區域,坦白說以 UI 來講是很糟糕的設計,不像舊版只要點擊該篇文章的空白處就能選取。


C. 編輯文章

相信不少人跟我一樣,找半天不知從何處編輯文章,答案是點擊 C 處的文章標題。

我是覺得這樣的設計不夠直覺,只能說適應久了會習慣。

而關於新版文章編輯器的功能變革,請見上一篇「2020 Blogger 新版文章編輯器使用心得」。


D. 標籤

關於標籤的操作必須給予肯定,因為舊版標籤操作有 bug,容易造成慘劇,可參考「Blogger 批次修改標籤的方法及注意事項」,而新版已修正問題。


E. 草稿及分頁

舊版有兩處功能在新版找不到:草稿文章數及分頁。

原來「草稿」、「已發佈」文章的數量藏在 E 處,點擊下拉三角形按鈕就會出現。

舊版的分頁功能就真的不見了,取而代之的是「瀑布流」設計,也就是往下捲後較舊的文章會持續載入

坦白說這是缺乏效率的設計,通常我逛到瀑布流的網頁只會覺得很蠢,因為頁尾擺放的資訊永遠沒機會看到。而新版後台使用瀑布流則是操作十分不便,舊版只要切換頁數就能看到幾個月前的文章、或查閱後台文章瀏覽量,現在不知要往下捲動多久才能跑完舊文章,更何況如果網站有上千篇文章時怎麼辦?

當然我瞭解官方的用意,一定是認為只要使用搜尋就可解決搜尋舊文章的問題,但是要搜尋也得每次都記得住關鍵字才行喔,而且如果只是想調查瀏覽量,現在就很麻煩了


F. 搜尋功能

為了能夠有效搜尋舊文章,官方的確大幅改善了後台的搜尋功能,這部分獨立拉出一個章節來介紹。



二、搜尋功能


1. 參數設定

在前圖 F 區塊的右邊,有個問號圖案,點進後是這個頁面,算是「搜尋」功能的說明書:



以下只整理使用機率比較高的參數:

  • 搜尋文章標題中的文字
    • 參數 → title:
    • 範例 → title:錨點
    • 使用這個參數後會限定只搜尋文章標題的字串,搜尋速度會快很多
  • 搜尋文章內文中的文字
    • 參數 → body:
    • 範例 → body:錨點
    • 使用這個參數後會搜尋文章內容的字串,只要網站的文章數越多,搜尋速度會越慢
  • 限定字串搜搜尋
    • 參數 → 字串前後用雙引號包起來 ""
    • 範例 → "使用錨點的操作方式"
    • 其實這就是 Google 搜尋的技巧,此用法可搭配其他參數
  • 搜尋多個字詞
    • 參數 → 小寫逗號 ,
    • 範例 → 錨點,技巧
    • 這一點跟平常的 Google 搜尋技巧不一樣,一般是用空格,這裡用逗號
  • 篩選在特定時間範圍
    • 參數
      • 更新日期起始於 → start_updated_date:
      • 更新日期結束於 → end_updated_date:
      • 發佈日期起始於 → start_published_date:
      • 發佈日期結束於 → end_published_date:
      • 建立日期起始於 → start_created_date:
      • 建立日期結束於 → end_created_date:
    • 範例
      • start_updated_date:2020-06-05
      • 日期的使用請注意格式
    • 由於後台文章列表變成瀑布流了,沒有分頁功能,想要列出較舊的文章,新版介面只能熟悉以上的參數,來篩出特定日期區間的文章

2. 其他參數

至於其他參數,大部分其實用不到,或者說可以有更好的操作方式:

  • 依狀態篩選 → 請使用本篇「一、文章、網頁」→「E. 草稿」這個區塊即可
  • 依標籤搜尋文章 → 請使用本篇「一、文章、網頁」→「D. 標籤」這個區塊即可
  • 按作者搜尋(author:) → 除非網誌有多個作者才用得到


3. 不使用參數

如果搜尋沒使用參數的話,等於使用舊版的搜尋功能,會搜尋文章內文,只要網站的文章數越多,搜尋速度會越慢。

不過這裡 Blogger 有修正一個嚴重的問題,FB 社團這個討論串「Blogger 後台只能搜尋到最新 1000 篇文章」有成員提出這個現象,經實測後,現在可以搜尋到 1000 篇以後的舊文章了



三、版面配置


1. 網站小圖示

很多人都反應原本的「網站小圖示」不見了,原來官方新版後台把這個功能移到「設定」→「基本」的最後一項。


2. 功能按鈕

2020-blogger-new-dashboard-2.jpg-Blogger 2020 後台介面及功能變革整理

其實新版「版面配置」的 UI 跟以前差別不大,主要是功能按鈕全部跑到右下角了,可能會找不到。

  • 編輯完之後記得按右下角的儲存圖示,才會發生作用
  • 多了一個取消的打叉圖示,可以還原修改之前的狀態



四、主題


遇到太多案例跟我反應,表示「怎麼編輯範本?怎麼備份還原?」,這些都是很常用的基本操作功能,但是新版後台改得讓人找不到這些選項,我覺得 UI 部門需要檢討一下。


2020-blogger-new-dashboard-3.jpg-Blogger 2020 後台介面及功能變革整理

進入新版「後台」→「主題」後,現在只會看到上圖這樣,明明右邊空蕩蕩一片,偏偏要把所有選項藏在紅框裡的「淡灰色三個小點選單圖示」。

既然「自訂」按鈕可以獨立使用,其他按鈕的使用頻率會比「自訂」還低嗎?


2020-blogger-new-dashboard-4.jpg-Blogger 2020 後台介面及功能變革整理

點擊選單後,會讓人有柳暗花明又一村的感覺,那些消失的功能回來啦:「備份」、「還原」、「編輯 HTML」、「行動裝置設定」。

我覺得官方的意圖也許是,最好使用者都不要改範本,免得常常出問題來投訴,所以乾脆先把選項藏起來?



五、設定


1. 前面有提過,「網站小圖示」被移到「基本」這裡。

2. 有使用者反應,在「權限」的區塊,邀請其他作者後,無法設定為「管理員」。雖然可以選擇管理員後按「儲存」,但又會自動跳回「作者」,官方需要修復這個嚴重的問題

3. 其他的部分只是 UI 介面變更而已,變化不大。有一點比較奇特,網域設定的部分,多了一個「後援子網域」不知作用為何,但因為跟網域有關,最好別亂設定,如有高手知道這部分的功能歡迎指教。



六、總結


一樣使用前一篇的結語,站長們可參考本篇說明,針對自己覺得不好的地方,從後台跟官方反應,冀望 Blogger 在七月底前能做出改善,否則之後就只能強制使用新版介面及功能了。


更多 Blogger 相關文章:
Viewing all 571 articles
Browse latest View live