怎麼有一種我標題越下越宅的感覺......
我相信同好應該一看就知道我在跟哪一部致敬吧XD
總之,正規表示式就是用在你要找出 match 某個 pattern 的字串,
正規表示式就是你要事先訂好的 pattern,
例如你想在一篇文章中找出含有 cathy 的句子,
正規表示式就要訂為 /cathy/ 。所以正規表示式學好讓你可以跟電腦告白應該是沒問題的。~
其實會想挑戰 正規表示式 是因為昨天的題目,
偶然發現了鐵人賽系列文的 RSS 長這樣:
所以想要去問資料回來後取得 title 跟 link,
再將之列出來!
其實問 RSS 資料的方法跟昨日提到的一樣,
讓我們把 URL 改成 RSS 的網址試試看吧!
// 拿即時更新的 JSON 檔
let requestURL = "https://ithelp.ithome.com.tw/rss/series/3573";
let xhr = new XMLHttpRequest();
xhr.open("GET",requestURL,true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.responseType = 'json';
xhr.send();
// onload 是等資料拿到的時候才執行
xhr.onload = function(){
// responseData 設為拿到的回傳 JSON
let responseData = xhr.response;
console.log(responseData);
}
null?怎麼會是 null?
看到錯誤或結果不如預期的時候不要怕,
console.log 是我們的好朋友,
那我們不要拿 xhr.response,
只拿 xhr 看看:
console.log(xhr);
xhr 有回傳回來的東西,
一個一個點開來看,
發現在 responseXML 有寫到相關的錯誤訊息:
然後我就會想,啊,因為這次的 RSS 其實是 XML 格式,
會不會是因為它不支援 json 所以噴錯呢?
讓我們把 xhr.responseType = 'json' 註解掉再試一遍:
// 拿即時更新的 JSON 檔
let requestURL = "https://ithelp.ithome.com.tw/rss/series/3573";
let xhr = new XMLHttpRequest();
xhr.open("GET",requestURL,true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// xhr.responseType = 'json'; // 註解掉試試看
xhr.send();
// onload 是等資料拿到的時候才執行
xhr.onload = function(){
let responseData = xhr.response;
console.log(xhr);
}
哦哦哦,看起來有拿到東西了!
讓我們就可以開始今日的課題了!
原因昨天的文章有提到XD
就是小的還太弱,如果還在練習正規表示式,
我就被 鐵人賽 RSS 視為攻擊就不好了,
所以就一樣在最前面宣告變數放靜態資料。
但因為內容龐大,先貼個 title + link 附近幾行的內容意思意思一下就好,
像這樣:
let responseData = `<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<title>30天找回寫程式手感計劃!!! :: 第 12 屆 iT 邦幫忙鐵人賽</title>
<link>https://ithelp.ithome.com.tw/users/20129873/ironman</link>
<item>
<title>Day17 - Open Data x JavaScript x JSON ( 1/2 )</title>
<link>https://ithelp.ithome.com.tw/articles/10242719?sc=rss.iron</link>
<guid isPermaLink="true">https://ithelp.ithome.com.tw/articles/10242719?sc=rss.iron</guid>
<description><![CDATA[<p><del>這絕對不是向獵人致敬的標題哦XD</del><br />
<pubDate>2020-09-23 22:24:58</pubDate>
</item>
<item>
<title>Day16 - 雖然很久沒有國際賽事,還是要用 JavaScript 關心一下小戴的 World Rankings!─ addEventListener 篇</title>
<link>https://ithelp.ithome.com.tw/articles/10242034?sc=rss.iron</link>
<guid isPermaLink="true">https://ithelp.ithome.com.tw/articles/10242034?sc=rss.iron</guid>
<description><![CDATA[<p>對不起,在下小的我要用小戴女神撐過 2 天了QQ<br />`;
console.log(`responseData 是: ${responseData}`);
正規表示式我沒有很常寫,
所以格式語法我背不起來orz
讓我們站在巨人的肩膀上吧→
正規表示式 Regular Expression
[JS] 正則表達式(Regular Expression, regex)
這是我在寫卡關時最常參考的 2 篇,
然後中間我卡關的地方就不一一在這裡貼出了,
直接貼出我試的結果:
let matchPattern = new RegExp('<title>.+', 'g'); // 訂定正規表示式的比對 Pattern
let matchResult = responseData.match(matchPattern);
if ( matchResult.length > 0 ){
for ( let i=0; i<matchResult.length;i++ ){
console.log(`${matchResult[i]}`);
}
}
看起來有比對到我們要的樣子,
這邊講解一下 Pattern 的訂定:
<title>.+
意思是要找到含 <title>
且後面至少包含 1 個任意字元。RegExp('<title>.+', 'g')
RegExp('<title>.+', 'i')
,RegExp('<title>.+', 'gi')
String.prototype.match():以陣列回傳字串中匹配到的部分,否則回傳 null。
let requestURL = "https://ithelp.ithome.com.tw/rss/series/3573";
let xhr = new XMLHttpRequest();
xhr.open("GET",requestURL,true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// xhr.responseType = 'json';
xhr.send();
// onload 是等資料拿到的時候才執行
xhr.onload = function(){
// responseData 設為拿到的回傳資料
let responseData = xhr.response;
// let responseData = xhr;
// *****等拿到資料再進行後面字串比對
// *****如果沒有這樣寫,則會跟前面同時執行,就會因為沒資料而出錯
compareData(responseData);
}
function compareData(responseData){
let matchPattern = new RegExp('<title>.+', 'g'); // g: global 的意思,找到之後會繼續往後配對
let matchResult = responseData.match(matchPattern);
if ( matchResult.length > 0 ){
console.log("有包含 title");
for ( let i=0; i<matchResult.length;i++ ){
console.log(`${matchResult[i]}`);
}
}
}
雖然比到了很開心,
但有沒有發現一件事情?
我們要取的只有標籤裡面的內容,
並非整行.......
好吧,還是先弄回靜態資料,
繼續克服這個難關吧。
這邊小的硬弄出來了,
寫法可能不是很好,
(因為我不知道要怎麼用該 Pattern 比對,可是又讓比對結果不包含 Pattern orz)
但有試出來就好,
之後再 tune 個寫法。
matchPattern = new RegExp('>.+<', ''); // 找出包含在 > < 中間的字
matchResult_content = responseData.match(matchPattern);
console.log(`${matchResult_content[0]}`);
let str = matchResult_content[0].replace(/>/, '').replace(/</, ''); // 然後再用 replace 把 < >取代成空白 (JavaScript支援 .replace.replace 的寫法)
console.log(`str: ${str}`);
弄出來了!
剩下的就是把結果用到網頁上呈現就好!
別忘了還要附上連結哦!
這邊我的做法是先比對有含 >< 的字串,
再用 replace 將 >< 取代成空白。
html:
<h3>第 12 屆 iT 邦幫忙鐵人賽</h3>
<h3>「30天找回寫程式手感計劃!!!」系列文 RSS</h3>
<ul id="articleList"></ul>
JavaScript:
const articleListElement = document.getElementById("articleList");
let articleListHTML = "";
let matchArray = compareData(responseData);
for ( let x=0; x<matchArray.length;x++ ){
articleListHTML += `<li><a href="${matchArray[x].Link}" target="_blanck">${matchArray[x].Title}</a></li>`;
}
articleListElement.innerHTML = articleListHTML;
function compareData(responseData){
let matchArray = [];
let matchPattern = new RegExp('<title>.+', 'g'); // g: global 的意思,找到之後會繼續往後配對
let matchResult_title = responseData.match(matchPattern);
matchPattern = new RegExp('<link>.+', 'g');
matchResult_link = responseData.match(matchPattern);
if ( matchResult_title.length > 0 ){
for ( let i=0; i<matchResult_title.length;i++ ){
matchPattern = new RegExp('>.+<', '');
matchResult_content = matchResult_title[i].match(matchPattern);
matchResult_title[i] = matchResult_content[0].replace(/>/, '').replace(/</, '');
matchResult_content = matchResult_link[i].match(matchPattern);
matchResult_link[i] = matchResult_content[0].replace(/>/, '').replace(/</, '');
matchArray.push({Title:matchResult_title[i],Link:matchResult_link[i]}); // 將 trim 過的 title & link 存起來
}
}
return matchArray;
}
やった!(太好了!)
讓我們一鼓作氣再改成動態取資料試試看吧!
let requestURL = "https://ithelp.ithome.com.tw/rss/series/3573";
let xhr = new XMLHttpRequest();
xhr.open("GET",requestURL,true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// xhr.responseType = 'json';
xhr.send();
// onload 是等資料拿到的時候才執行
xhr.onload = function(){
// responseData 設為拿到的回傳資料
let responseData = xhr.response;
// let responseData = xhr;
// *****等拿到資料再進行後面字串比對等邏輯
// *****如果沒有這樣寫,則會跟前面同時執行,就會因為沒資料而出錯
let matchArray = compareData(responseData);
for ( let x=0; x<matchArray.length;x++ ){
articleListHTML += `<li><a href="${matchArray[x].Link}" target="_blanck">${matchArray[x].Title}</a></li>`;
}
articleListElement.innerHTML = articleListHTML;
}
本日打完收工!
覺得今天有很多程式碼都寫得很重複,
但先求有再求好,
正規表示式果然博大精深XD
覺得應該要好幾天都來寫正規表示式才行!!!!!