

<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>html &#8211; Max的程式語言筆記</title>
	<atom:link href="https://stackoverflow.max-everyday.com/tag/html/feed/" rel="self" type="application/rss+xml" />
	<link>https://stackoverflow.max-everyday.com</link>
	<description>我要當一個豬頭，快樂過每一天</description>
	<lastBuildDate>Fri, 06 Oct 2023 09:15:27 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://stackoverflow.max-everyday.com/wp-content/uploads/2017/02/max-stackoverflow-256.png</url>
	<title>html &#8211; Max的程式語言筆記</title>
	<link>https://stackoverflow.max-everyday.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>using python, Remove HTML tags/formatting from a string</title>
		<link>https://stackoverflow.max-everyday.com/2023/10/using-python-remove-html-tags-formatting-from-a-string/</link>
					<comments>https://stackoverflow.max-everyday.com/2023/10/using-python-remove-html-tags-formatting-from-a-string/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Fri, 06 Oct 2023 09:15:26 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[String]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=5073</guid>

					<description><![CDATA[在使用 selenium 時, 之前使用 ele...]]></description>
										<content:encoded><![CDATA[
<p>在使用 selenium 時, 之前使用 element.text 都可以正確地取得  TEXT 內容, 很奇怪, 目前使用 selenium 4.13.0 + python 3.9.13 在 Win 10 環境, 有時候會正常, 但有時會失敗, 可以確定取得的內容是正確的, 取得的 innerHTML 長這樣:</p>



<pre class="wp-block-code"><code>&lt;div data-v-337697a8="" class="sesstion-item">&lt;div data-v-337697a8="" class="row pa-4 flex-column flex-sm-row no-gutters">&lt;div data-v-337697a8="" class="col-sm-10 col-md-10 col-12">&lt;div data-v-337697a8="" class="row mx-0 flex-column flex-md-row no-gutters">&lt;div data-v-337697a8="" class="d-flex text-left font-weight-bold text-regular py-2 is-word-break col-sm-12 col-md-4 col-12 align-self-center">
                2023 JO1 1ST ASIA TOUR 'BEYOND THE DARK' LIMITED EDITION IN TAIPEI
              &lt;/div>&lt;div data-v-337697a8="" class="px-md-2 d-flex justify-md-center align-left align-md-center col-sm-12 col-md-2 col-12">&lt;div data-v-337697a8="" class="d-flex mb-2 mb-md-0">&lt;div data-v-337697a8="" class="grey--text text--darken-1 d-block d-md-none mr-2 wordBreakKeepAll">日期&lt;/div>&lt;div data-v-337697a8="">2023-11-11(六)&lt;/div>&lt;/div>&lt;/div>&lt;div data-v-337697a8="" class="px-md-2 d-flex justify-md-center align-md-center col-sm-12 col-md-2 col-12">&lt;div data-v-337697a8="" class="d-flex mb-2 mb-md-0">&lt;div data-v-337697a8="" class="grey--text text--darken-1 d-block d-md-none mr-2 wordBreakKeepAll">時間&lt;/div>&lt;div data-v-337697a8="">19:00&lt;/div>&lt;/div>&lt;/div>&lt;div data-v-337697a8="" class="px-md-2 d-flex justify-md-center align-md-center is-word-break col-sm-12 col-md-4 col-12">&lt;div data-v-337697a8="" class="d-flex mb-2 mb-md-0">&lt;div data-v-337697a8="" class="grey--text text--darken-1 d-block d-md-none mr-2 wordBreakKeepAll">地點&lt;/div>&lt;div data-v-337697a8="" class="text-left text-md-center location-content">
                    Zepp New Taipei
                    &lt;div data-v-337697a8="" class="grey--text text--darken-3 text-small d-inline d-md-block">
                      新北市新莊區新北大道四段3號8樓
                    &lt;/div>&lt;/div>&lt;/div>&lt;/div>&lt;/div>&lt;/div>&lt;div data-v-337697a8="" class="font-weight-bold col-sm-2 col-md-2 col-12 align-self-center">&lt;hr data-v-337697a8="" role="separator" aria-orientation="horizontal" class="d-block d-sm-none mb-5 mt-3 v-divider theme--light">&lt;div data-v-9536f93e="" data-v-337697a8="">&lt;!---->&lt;!---->&lt;!---->&lt;!---->&lt;button data-v-9536f93e="" type="button" class="nextBtn float-right v-btn v-btn--block v-btn--has-bg v-btn--rounded theme--dark v-size--default">&lt;span class="v-btn__content">立即購票&lt;/span>&lt;/button>&lt;!---->&lt;/div>&lt;/div>&lt;/div>&lt;!---->&lt;/div></code></pre>



<p>使用 .text 取得內容, 居然是空值! 但多試幾次, 偶爾可以取得正確的 text, 既然可以拿 innerHTML 就自己來去 tag 就好了. </p>



<pre class="wp-block-code"><code>import re
def striphtml(data):
    p = re.compile(r'&lt;.*?>')
    return p.sub('', data)

>>> striphtml('&lt;a href="foo.com" class="bar">I Want This &lt;b>text!&lt;/b>&lt;/a>')
'I Want This text!'</code></pre>



<p>Below you will find the syntax which require as per different binding. Change the&nbsp;<code>innerHTML</code>&nbsp;to&nbsp;<code>outerHTML</code>&nbsp;as per required.</p>



<p>Python:</p>



<pre class="wp-block-code"><code>element.get_attribute('innerHTML')</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2023/10/using-python-remove-html-tags-formatting-from-a-string/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[Javascript] 學習 Promise</title>
		<link>https://stackoverflow.max-everyday.com/2019/12/javascript-promise/</link>
					<comments>https://stackoverflow.max-everyday.com/2019/12/javascript-promise/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Wed, 11 Dec 2019 16:12:31 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=3137</guid>

					<description><![CDATA[隨手研究一下 recaptcha 的 javas...]]></description>
										<content:encoded><![CDATA[
<p>隨手研究一下 recaptcha 的 javascript ，發現一個沒學過的物件 Promise，Google 來學習一下。我服用的是下列這篇文章，講解的很詳細：</p>



<p>你懂 JavaScript 嗎？#24 Promise<br><a href="https://cythilya.github.io/2018/10/31/promise/">https://cythilya.github.io/2018/10/31/promise/</a></p>



<p>心得，網路上的神人真是多。學海無涯。</p>



<hr class="wp-block-separator"/>



<p>如果你也看完上面的文章，首先我遇到第一個「恐龍時代」的範例就看不懂了，還好，在程式多處加入log() 就看懂了，增加超多 log() 的範例：</p>



<pre class="wp-block-code"><code>function fetchA(cb) {
  console.log("do A job");

  setTimeout(function() { // 模擬冗長運算
  	console.log("return A job");
    return cb(1);
  }, 3000);
}

function fetchB(cb) {
  console.log("do B job");
  
  setTimeout(function() { // 模擬冗長運算
  	console.log("return B job");
    return cb(2);
  }, 1000);
}

function add(getX, getY, cb) {
  var x, y;

  console.log("push getX()");
  getX(function(xVal) {
	console.log("do function xVal");
    x = xVal; // 得到 x
    y &amp;&amp; cb(x, y); // 若 y 也取到了，就執行加法運算
	console.log("finish function xVal");
  });

  console.log("push getY()");
  getY(function(yVal) {
	console.log("do function yVal");
    y = yVal; // 得到 y
    x &amp;&amp; cb(x, y); // 若 x 也取到了，就執行加法運算
	console.log("finish function yVal");
  });
}

add(fetchA, fetchB, function(a, b) {
  console.log(a + b); // 加法運算，印出相加結果
});</code></pre>



<hr class="wp-block-separator"/>



<p>執行結果：</p>



<pre class="wp-block-code"><code>> "push getX()"
> "do A job"
> "push getY()"
> "do B job"
> "return B job"
> "do function yVal"
> "finish function yVal"
> "return A job"
> "do function xVal"
> 3
> "finish function xVal"</code></pre>



<hr class="wp-block-separator"/>



<p>似乎有沒有看懂古時候的寫法，和Promise 物件的用法都沒什麼關係，呵呵。</p>



<hr class="wp-block-separator"/>



<h4 class="wp-block-heading">相關文章：</h4>



<p>Promise<br><a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise">https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Promise</a></p>



<p>Promise 物件代表一個即將完成、或失敗的非同步操作，以及它所產生的值。</p>



<p>此條目為介紹 Promise 建構式。要瞭解 Promise 相關使用方式，請先參考使用 Promise。Promise 建構式主要用於包裹尚未支援 Promise 的函式。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2019/12/javascript-promise/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Selenium 使用 Firefox 瀏覽器 webdriver</title>
		<link>https://stackoverflow.max-everyday.com/2018/11/selenium-firefox-webdriver/</link>
					<comments>https://stackoverflow.max-everyday.com/2018/11/selenium-firefox-webdriver/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 29 Nov 2018 07:05:52 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[BOT]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[selenium]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=2483</guid>

					<description><![CDATA[如果你不會寫程式，可以匯錢給我下載執行檔。目前是...]]></description>
										<content:encoded><![CDATA[
<p>如果你不會寫程式，可以匯錢給我下載執行檔。目前是套用在 Firefox瀏覽器，如果你是chrome瀏覽器的愛好者請參考這一篇：Selenium 使用 Chrome 瀏覽器 webdriver<br><a href="https://stackoverflow.max-everyday.com/2018/03/selenium-chrome-webdriver/">https://stackoverflow.max-everyday.com/2018/03/selenium-chrome-webdriver/</a></p>



<p>使用Firefox 搶票的執行畫面：拓元售票系統使用Firefox+Max自動搶票機器人(2018/11/29)<br><a href="https://www.youtube.com/watch?v=umjVjW0b4cc">https://www.youtube.com/watch?v=umjVjW0b4cc</a></p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="拓元售票系統使用Firefox+Max自動搶票機器人(2018/11/29)" width="640" height="480" src="https://www.youtube.com/embed/umjVjW0b4cc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>附註：使用 Firefox + webdriver 時會造成 javascript 的彈出式詢問對話框(confirm dialog) 無法正常使用，請點選「訂單查詢」在第2個分頁裡去取消或結帳。</p>



<p>接下來的步驟是寫給想要「練功」或「有一些電腦基礎」而且有辦法在「命令提示字元」(Windows平台)或的終端機(Linux/Mac平台）執行指令的人。</p>



<hr class="wp-block-separator"/>



<p>Step 1：要安裝 python</p>



<p>附註1：如果是 Linux 或 MacOS 平台，可以略過 Step1，因為內建就有 python, python2 或 python3 都可以，不限定版本。<br>附註2：除了python 如果你懂其他程式語言(例如：java)也可以實作，不限於python程式語言，大同小異）</p>



<p>Step 2：要安裝 pip</p>



<p>附註：這個太簡單，如果你的電腦裡沒有pip 指令，自行google 看看如何安裝。</p>



<p>Step 3：安裝selenium套件，請執行指令：</p>



<pre class="wp-block-preformatted"> pip install selenium</pre>



<hr class="wp-block-separator"/>



<p>如果在 Linux 或 MacOS 平台裡執行pip install 失敗，請先pip install virtualenv. 我自己本身是使用&nbsp; macOS, 一開始是無法安裝，使用 virtualenv，是一定可以跑，後來不知道修改到什麼，變成不用進入 venv 環境裡也可以直接執行。</p>



<p>如果是 Windows平台，請直接跳到 Step 4.</p>



<p>virtualenv 基礎教學：<br><a href="http://docs.python-guide.org/en/latest/dev/virtualenvs/">http://docs.python-guide.org/en/latest/dev/virtualenvs/</a></p>



<hr class="wp-block-separator"/>



<p>Step 4：下載 geckodriver (WebDriver for Firefox)</p>



<p>geckodriver 下載頁面：</p>



<p><a href="https://github.com/mozilla/geckodriver/releases">https://github.com/mozilla/geckodriver/releases</a></p>



<p>附註1：geckodriver 目前有支援 Linux 64bit / macOS 64bit / Windows 32bit (64bit 也可以執行 32bit程式） / Windows 64bit 等版本。Linux 是有推出 32bit 的，但這個年代幾乎沒有人再去安裝 32bit 的作業系統了。</p>



<p>太舊的 Firefox 執行起來會有問題，請先更新Firefox瀏覽器為最近的版本。</p>



<p>附註：firefox 有分 32bit 和 64bit, 請下載正確的版本，要知道firefox&nbsp; 的版本在「說明」-「關於FireFox」裡可以看到。</p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="1252" height="724" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/11/Screen-Shot-2019-01-25-at-04.39.30.jpg" alt="" class="wp-image-2607" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/11/Screen-Shot-2019-01-25-at-04.39.30.jpg 1252w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/11/Screen-Shot-2019-01-25-at-04.39.30-600x347.jpg 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/11/Screen-Shot-2019-01-25-at-04.39.30-768x444.jpg 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/11/Screen-Shot-2019-01-25-at-04.39.30-1024x592.jpg 1024w" sizes="(max-width: 1252px) 100vw, 1252px" /></figure>



<p>完成 step 3 的 selenium 的安裝，和 step 4 下載geckodriver 之後，先試看看這個sample code:</p>



<pre class="wp-block-preformatted">from selenium import webdriver
# for selenium 4
from selenium.webdriver.chrome.service import Service

driverpath = "/Users/max/Documents/chromedriver"
firefox_service = Service(<meta charset="utf-8">driverpath)
driver = webdriver.Firefox(service=<meta charset="utf-8">firefox_service)
driver.get("http://tw.yahoo.com/")</pre>



<p>說明1：這個driverpath 路徑請換成您電腦實際下載的資料夾。</p>



<p>說明2：這個範例會開一個新的 Firefox 視窗並連到網址&nbsp;http://tw.yahoo.com/</p>



<p>附註：目前的範例是透過 python 去控制 selenium ＋ geckodriver，如果你懂其他的程式語言，也是可以實作的出來，異曲同工。</p>



<hr class="wp-block-separator"/>



<p>範例 2 號：</p>



<pre class="wp-block-preformatted">from selenium import webdriver
# for selenium 4
from selenium.webdriver.chrome.service import Service

driverpath = "/Users/max/Documents/chromedriver"
firefox_service = Service(driverpath)
driver = webdriver.Firefox(service=firefox_service)</pre>



<pre class="wp-block-preformatted">driver.get('http://www.cwb.gov.tw/V7/')
driver.set_window_position(0,0) #瀏覽器位置
driver.set_window_size(700,700) #瀏覽器大小

driver.find_element_by_link_text('天氣預報').click() #點擊頁面上"天氣預報"的連結</pre>



<hr class="wp-block-separator"/>



<p>因為 webdriver 的使用方式相同，所以接下來的介紹請參考這一篇：<br><a href="https://stackoverflow.max-everyday.com/2018/03/selenium-chrome-webdriver/">https://stackoverflow.max-everyday.com/2018/03/selenium-chrome-webdriver/</a></p>



<p>現在已經來到 selenium 4.0 之後的版本，網路上部份舊版的範例是使用 executable_path 參數，會顯示提示的訊息說直接使用上面的範例可能會顯示錯誤訊息，因為 selenium 需要傳遞 service :</p>



<pre class="wp-block-preformatted">DeprecationWarning: executable_path has been deprecated, please pass in a Service object
driver = webdriver.Firefox(executable_path=driver_path)</pre>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2018/11/selenium-firefox-webdriver/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>how to reset css to default settings</title>
		<link>https://stackoverflow.max-everyday.com/2018/03/how-to-reset-css-to-default-settings/</link>
					<comments>https://stackoverflow.max-everyday.com/2018/03/how-to-reset-css-to-default-settings/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Sun, 25 Mar 2018 12:01:18 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[html]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=2173</guid>

					<description><![CDATA[當 css 變的複雜的時候，會繼承到很多奇怪的 ...]]></description>
										<content:encoded><![CDATA[<p>當 css 變的複雜的時候，會繼承到很多奇怪的 css 設定值，造成無法達成預設的效果，我遇到的情況是：</p>
<p>max-width: 100%</p>
<p>但套用這個設定值會讓圖片變小，我想修改成顯示原圖大小，並置右，解法如下：</p>
<blockquote>
<pre>.carousel .item img {
 float: right;
 max-width: <span style="color: #ff0000;">initial</span>;
}</pre>
</blockquote>
<p>這裡的 carousel 是直接修改 bootstrap 的 sample code.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2018/03/how-to-reset-css-to-default-settings/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Selenium 使用 Chrome 瀏覽器 webdriver</title>
		<link>https://stackoverflow.max-everyday.com/2018/03/selenium-chrome-webdriver/</link>
					<comments>https://stackoverflow.max-everyday.com/2018/03/selenium-chrome-webdriver/#comments</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 01 Mar 2018 06:54:24 +0000</pubDate>
				<category><![CDATA[Python筆記]]></category>
		<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[BOT]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[selenium]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=2093</guid>

					<description><![CDATA[這篇文章要分享如何實作你己的搶票機器人，如果你不...]]></description>
										<content:encoded><![CDATA[
<p>這篇文章要分享如何實作你己的搶票機器人，如果你不會寫程式，針對電腦只會使用滑鼠的使用者，目前我們有提供點2下就可以動的執行檔，請參考教學影片：</p>



<p>拓元售票系統使用Max自動搶票機器人(2018/11/23)<br><a href="https://www.youtube.com/watch?v=QX8u2iF1Gm8">https://www.youtube.com/watch?v=QX8u2iF1Gm8</a></p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="拓元售票系統使用Max自動搶票機器人(2018/11/23)" width="640" height="480" src="https://www.youtube.com/embed/QX8u2iF1Gm8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>上面影片裡的exe執行檔的下載點：Max的拓元搶票機器人<br><a href="https://max-everyday.com/2018/03/tixcraft-bot/">https://max-everyday.com/2018/03/tixcraft-bot/</a></p>



<p>Max搶票機器人的Facebook粉絲團：<br><a href="https://www.facebook.com/maxbot.ticket/">https://www.facebook.com/maxbot.ticket/</a></p>



<hr class="wp-block-separator has-css-opacity"/>



<p>2018-12-14 的版本可以指定日期和區域：<a href="https://www.youtube.com/watch?v=tSOBgcrMmuA">https://www.youtube.com/watch?v=tSOBgcrMmuA</a></p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="拓元售票系統使用Max自動搶票機器人(2018/12/14)" width="640" height="480" src="https://www.youtube.com/embed/tSOBgcrMmuA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<hr class="wp-block-separator has-css-opacity"/>



<p>如果你是Firefox瀏覽器的愛好者請參考這一篇：Selenium 使用Firefox 瀏覽器 webdriver<br><a href="https://stackoverflow.max-everyday.com/2018/11/selenium-firefox-webdriver/">https://stackoverflow.max-everyday.com/2018/11/selenium-firefox-webdriver/</a></p>



<hr class="wp-block-separator has-css-opacity"/>



<p>接下來文章內容是要寫給想要「練功」(寫程式)或「有一些電腦基礎」而且有辦法在「命令提示字元」(Windows平台)或的終端機(Linux/Mac平台）執行指令的人。</p>



<hr class="wp-block-separator has-css-opacity"/>



<p><strong>Step 1：安裝 python</strong></p>



<p>如果是 Linux 或 MacOS 平台，如果內建的版本是 python 2 的的，因為目前已經不支援，請下載並安裝 python 3 ，不限定版本，建議到 python 的官方網站下載並安裝最新 python 3.x 的版本。目前(2023年4月)比較穩定的版本似乎  python 3.9 或 python 3.10, 而 python 3.11 似乎太新了, 相容性還沒有很好。 </p>



<p>除了python 如果你懂其他程式語言(例如：java 或 C#)也可以實作，不限於python程式語言，各個程式語言之間大同小異）</p>



<p>selenium 可以支援的程式語言，參考看看:<br><a href="https://www.selenium.dev/documentation/">https://www.selenium.dev/documentation/</a></p>



<p><strong>Step 2：安裝 pip</strong></p>



<p>附註：這個太簡單，如果你的電腦裡沒有pip 指令，自行google 看看如何安裝。</p>



<p><strong>Step 3：安裝selenium套件，請執行指令：</strong></p>



<pre class="wp-block-preformatted">pip install selenium</pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>如果在 Linux 或 MacOS 平台裡執行pip install 失敗，請先pip install virtualenv. 我自己本身是使用  macOS, 一開始是無法安裝，使用 virtualenv，是一定可以跑，後來不知道修改到什麼，變成不用進入 venv 環境裡也可以直接執行。</p>



<p>沒有使用 venv 也是可以的，但用過 venv 的人都很推薦使用，因為比較不會被其他專案使用的元件影響到，也不會去影響到其他專案。</p>



<p>如果是 Windows平台，請直接跳到 Step 4.</p>



<p>virtualenv 基礎教學：<br><a href="http://docs.python-guide.org/en/latest/dev/virtualenvs/">http://docs.python-guide.org/en/latest/dev/virtualenvs/</a></p>



<hr class="wp-block-separator has-css-opacity"/>



<p><strong>Step 4：下載ChromeDriver</strong></p>



<p>ChromeDriver 說明：</p>



<p>ChromeDriver 可以讓 Selenium Server 呼叫 Google Chrome 執行，ChromeDriver 網站：<br><a href="https://sites.google.com/a/chromium.org/chromedriver/">https://sites.google.com/a/chromium.org/chromedriver/</a></p>



<p>ChromeDriver 下載頁面：</p>



<p><a href="https://sites.google.com/a/chromium.org/chromedriver/downloads">https://sites.google.com/a/chromium.org/chromedriver/downloads</a></p>



<p>附註1：ChromeDriver目前有支援 Linux 64bit / macOS 64bit / Windows 32bit (64bit 也可以執行 32bit程式）</p>



<p>附註2：除了有&nbsp;ChromeDriver 還有&nbsp;<a href="https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari">SafariDriver</a>&nbsp;可以讓 Selenium Server 呼叫 Safari 瀏覽器來執行，參考看看 Safari Extension，建議使用ChromeDriver即可。</p>



<p>太舊的 chrome 執行起來會有問題，請先更新chrome瀏覽器為最近的版本，更新方式為：「設定」-&gt;「關於Chrome」。</p>



<figure class="wp-block-image"><img decoding="async" width="1024" height="671" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-11-09-16.55.07.jpg" alt="" class="wp-image-2470" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-11-09-16.55.07.jpg 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-11-09-16.55.07-600x393.jpg 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-11-09-16.55.07-768x503.jpg 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-11-09-16.55.07-380x250.jpg 380w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>完成 step 3 的 selenium 的安裝，和 step 4 下載ChromeDriver 之後，先試看看這個sample code:</p>



<pre class="wp-block-preformatted">from selenium import webdriver   <br>chromedriver = "/Users/max/Documents/chromedriver"<br>driver = webdriver.Chrome(chromedriver)<br>driver.get("http://tw.yahoo.com/")</pre>



<ul class="wp-block-list">
<li>說明1：這個ChromeDriver 路徑請換成您電腦實際下載的資料夾。</li>



<li>說明2：這個範例會開一個新的 chrome 視窗並連到網址&nbsp;http://tw.yahoo.com/</li>



<li>附註：目前的範例是透過 python 去控制 selenium ＋ chromedriver，如果你懂其他的程式語言，也是可以實作的出來。</li>
</ul>



<hr class="wp-block-separator has-css-opacity"/>



<p>範例 2 號：</p>



<pre class="wp-block-preformatted">from selenium import webdriver
 
chromedriver = "/Users/max/Documents/chromedriver"
driver = webdriver.Chrome(chromedriver)</pre>



<pre class="wp-block-preformatted">driver.get('http://www.cwb.gov.tw/V7/')
driver.set_window_position(0,0) #瀏覽器位置
driver.set_window_size(700,700) #瀏覽器大小

driver.find_element_by_link_text('天氣預報').click() #點擊頁面上"天氣預報"的連結
</pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>webdriver有許多方法，</p>



<p>範例 2 號使用的是find_element_by_link_text()，還有許多方法如下：</p>



<pre class="wp-block-preformatted">find_element_by_name()
find_element_by_id()
find_element_by_tag_name()
find_element_by_partial_link_text()
find_element_by_css_selector()</pre>



<p>另一種用法：</p>



<p>area = el.find_element(By.TAG_NAME, &#8220;a&#8221;)</p>



<ul class="wp-block-list">
<li>
By.TAG_NAME
</li>



<li>
By.CSS_SELECTOR
</li>
</ul>



<p>用法可以參考SeleniumHQ：</p>



<p><a href="http://www.seleniumhq.org/docs/03_webdriver.jsp">http://www.seleniumhq.org/docs/03_webdriver.jsp</a></p>



<hr class="wp-block-separator has-css-opacity"/>



<p>關於 macOS 的 Safari’s WebDriver</p>



<p>如果 macOS 版本是<strong>High Sierra and later</strong>，請Run: </p>



<p><code>safaridriver --enable</code> </p>



<p>once. (If you’re upgrading from a previous macOS release, you may need to use sudo.)</p>



<p>如果 macOS 版本是 <strong>Sierra and earlier:</strong></p>



<ol class="wp-block-list">
<li>If you haven’t already done so, make the Develop menu available. Choose Safari &gt; Preferences, and on the Advanced tab, select “<strong>Show Develop menu in menu bar</strong>.” For details, see&nbsp;<a href="https://support.apple.com/guide/safari/welcome">Safari Help</a>.</li>



<li>Choose Develop &gt; Allow Remote Automation.</li>



<li>Authorize&nbsp;<code>safaridriver</code>&nbsp;to launch the XPC service that hosts the local web server. To permit this, manually run&nbsp;<code>/usr/bin/safaridriver</code>&nbsp;once and follow the authentication prompt.</li>
</ol>



<hr class="wp-block-separator has-css-opacity"/>



<h4 class="wp-block-heading">常見問題(Q&amp;A)</h4>



<p><strong>Q:網速到底有沒有差?</strong><br>光世代有分300M/100M，100m/40m，請知道的是如果在同樣的操作環境，人也一樣，那300m的會不會比100m的更高的機率買到票? 到底什麼是比別人快買到票的關鍵因素?? 售票系統的運作原理是什麼? 為何我的手速也很快了，但為什麼一進去票就是都被買了?他們到底是什麼原因比我快進去，快送出購票請求??</p>



<p>A：高速的網路下載速度是有差異的，也許差幾個毫秒吧，以100Mbps和20Mbps來說下載一個拓元的網頁可能差異不大。</p>



<p>買票前建議先試著去買其他表演，事先下載好購票網頁會使用到的 javascript 和 css 檔案，可以透過離線檔案的快取(cache) 加速網頁的反應時間。</p>



<p>建議使用chrome 瀏覽器來搶票，反應時間會快一點。</p>



<p>「售票系統的運作原理」不難，google 一下就可以看到大量的實作和原理教學，在這裡就不詳述。以目前常見的網頁相關技術來說，在網路上大型的網站實作原理都大同小異，大致上會使用負載平衡（load balance）架構分散主機的網頁流量和要求，通常是（但不是絕對）在資料庫的伺服器那一段程式碼來決定那一個要求可以買到票的，大多數伺服器在處理排隊(queue)的要求是先進先出(first in first out)，所以如果你的網路早一點下載完網頁，早一點執行完javascript，早一點送出搶票的要求，理論上搶到票的機率會高一點。</p>



<p><strong>Q：您提到，拓元有分 detail 和 game, 連到game的網址，搶票才會快，假如一開始時間還沒到，「立即購票」的按鈕根本還沒出現，用這個方法，要怎麼使用呢??</strong><br>A：detail 網址和 game 網址是一樣的，是獨立的，在購票流程裡你可以對可以購票的場次各使用 detail 和 game 網址去訂一次票，就可以知道其中差異，速度上 game 網址也可以買到票，由於傳回的網頁裡的資訊還有所執行的javascript較少，理論上也許會快幾個毫秒。</p>



<p><strong>Q：用搶票機器人，跟手動的差別? 這個問題主要是問，機器人的速度跟用手動的速度，會差距明</strong>顯嗎?手的速度能不能贏過機器人?<br>A：我有放示範用的youtube影片，那個反應時間以人類手指和眼球速度應該無法超越。</p>



<p><strong>Q：能開發軟體嗎?讓不懂程式的人也可以用? </strong><br>A：<br>目前有執行檔，不懂程式的人可以在 Windows/Mac/Linux 平台上可以直接執行。<br>附註1：「搶票軟體」無法保證可以買的到票，也許還有很多其他人使用了機器人來搶票。<br>問題2：「搶票軟體」拓元網頁會改版，也許會造成功能不正常。</p>



<p><strong>Q：有試著安裝及研究python，也成執行了webdriver幾個範例，但是還是不了解要如何寫出與您所說一支小程式來搶票?</strong></p>



<p>A：請先學會如何透過python 程式自動去點畫面上的按鈕，或使用點2下就可以跑的執行檔。</p>



<p><strong>Q：怎麼像你一樣在已開啟及已登入的視窗執行python?</strong></p>



<p>A：python會全開啟一個全新的視窗，請使用該視窗去登入 Google/Facebook/Pixel Pin.</p>



<p><strong>Q：你的教程中，電腦用的是Linux的系統，Windows系統是無法使用嗎？</strong></p>



<p>A：Windows 也可以使用哦。而且語法相同。ChromeDriver目前有支援 Linux 64bit / macOS 64bit / Windows 32bit (64bit 也可以執行 32bit程式）檔案下載：<br><a href="http://chromedriver.chromium.org/downloads">http://chromedriver.chromium.org/downloads</a></p>



<figure class="wp-block-image"><img decoding="async" width="1256" height="662" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-10-22.29.13.jpg" alt="" class="wp-image-2328" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-10-22.29.13.jpg 1256w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-10-22.29.13-600x316.jpg 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-10-22.29.13-768x405.jpg 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-10-22.29.13-1024x540.jpg 1024w" sizes="(max-width: 1256px) 100vw, 1256px" /></figure>



<p><strong>Q：如何判斷某一個網址，去做特定事情？</strong><br>A：</p>



<pre class="wp-block-preformatted">while True:
    time.sleep(0.2)
    url = ""
    try:
        url = driver.current_url
    except Exception as exc:
        pass

    if url is None:
        continue
    else:
        if len(url) == 0:
            continue
    print(url)
</pre>



<p><strong>Q：google提供的擴充附件外掛 官方是不是會查出來?</strong></p>



<p>A：這不是google提供。不確定官方是不是查的出來，要查的出來的可能很低，難度也很高，難在伺服器端很難判斷用戶是否為機器人。</p>



<p><strong>Q：環境是Win10 64bit 執行畫面顯示，我雙擊 chromedriver 後，畫面顯示「Only local connections are allowed.」，是不是這個機械人不設海外購票？</strong></p>



<p>A：</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="764" height="161" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Chromediver.jpg" alt="" class="wp-image-2477" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Chromediver.jpg 764w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Chromediver-600x126.jpg 600w" sizes="(max-width: 764px) 100vw, 764px" /></figure>



<p>Starting ChromeDriver 2.44(&#8230;&#8230;) on port 9515<br>Only local connections are allowed.</p>



<p>直接執行&nbsp;chromedriver.exe 是會顯示上面的訊息沒錯，ChromeDriver 的架構如下：</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="877" height="103" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/architecture2.png" alt="" class="wp-image-2478" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/architecture2.png 877w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/architecture2-600x70.png 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/architecture2-768x90.png 768w" sizes="(max-width: 877px) 100vw, 877px" /></figure>



<p>說明：上面三個正方形各代表一個執行檔，你雙擊&nbsp;chromedriver.exe 是執行上面第二個正方形，最右邊的是chrome瀏覽器，最左邊的是我們寫的python應用程式，透過ChromeDriver可以認識的指令去操作ChromeDriver,&nbsp;ChromeDriver 進而在同一台電腦裡遠端去控制chrome瀏覽器。</p>



<hr class="wp-block-separator has-css-opacity"/>



<p>實際範例：</p>



<p>如果有一個html 長的像醬子：</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="887" height="108" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-04-09.55.11.jpg" alt="" class="wp-image-2301" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-04-09.55.11.jpg 887w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-04-09.55.11-600x73.jpg 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2018/03/Screenshot-2018-05-04-09.55.11-768x94.jpg 768w" sizes="(max-width: 887px) 100vw, 887px" /></figure>



<p>該按鈕的 html code:</p>



<pre class="wp-block-preformatted">&lt;input class="btn btn-next" data-href="/ticket/area/18_RBTW/4029" name="yt0" type="button" value="立即訂購"&gt;</pre>



<p>要取到該按鈕的 python code:</p>



<pre class="wp-block-preformatted">el = driver.find_element_by_css_selector('.btn-next')</pre>



<p>讓按鈕產生點擊的事件的 python code:</p>



<pre class="wp-block-preformatted">el.click()</pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>有可能會找不到element</p>



<p>How to use the try/except with Selenium Webdriver when having Exceptions on Python</p>



<p>To be able to use&nbsp;<a href="http://selenium-python.readthedocs.io/api.html#module-selenium.common.exceptions">required exception</a>&nbsp;you have to import it first with correct name (<code>NoSuchElement</code>&nbsp;-&gt;&nbsp;<code>NoSuchElementException</code>):</p>



<pre class="wp-block-code"><code>from selenium.common.exceptions import NoSuchElementException

try:
    WebDriver.find_element_by_css_selector('div&#91;class="..."')
except NoSuchElementException:
    ActionToRunInCaseNoSuchElementTrue</code></pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>Using JavaScript</p>



<pre class="wp-block-preformatted">element = driver.execute_script("return $('.cheese')[0]")</pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>設定 select 裡的值：</p>



<pre class="wp-block-preformatted">from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_tag_name("select"))
select.select_by_visible_text("Edam")</pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>勾選 checkbox ：</p>



<p>You can “toggle” the state of checkboxes, and you can use “click” to set</p>



<p>html:</p>



<pre class="wp-block-preformatted">&lt;input type="checkbox" value="1" name="TicketForm[agree]" id="TicketForm_agree"&gt;</pre>



<p>python code:</p>



<pre class="wp-block-preformatted">el = driver.find_element(By.CSS_SELECTOR, '#TicketForm_agree')
</pre>



<p>or</p>



<pre class="wp-block-preformatted">driver.execute_script("$('#TicketForm_agree').prop('checked', true);")</pre>



<p>附註：讓輸入框focus 請用 javascript：</p>



<pre class="wp-block-preformatted">$('#TicketForm_verifyCode').focus()</pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>WebDriver Status<br><a href="https://chromium.googlesource.com/chromium/src/+/master/docs/chromedriver_status.md">https://chromium.googlesource.com/chromium/src/+/master/docs/chromedriver_status.md</a></p>



<p>這些是目前 WebDriver 支援的指令。</p>



<hr class="wp-block-separator has-css-opacity"/>



<p>從目前的 source code 可以清楚的看到如何去使用 webdriver 物件。</p>



<p>下面的這個 chromedriver 切換 frame 的功能，如果你要是搶「熱門」的票，是遇不到的，熱門的場次都是「自動畫位」，所以不必自己去選坐位，自動選坐位會彈出在 iframe 裡，可以使用下面這行指令即可切換到選位的 iframe:</p>



<pre class="wp-block-preformatted">driver.switch_to.frame(driver.find_element_by_xpath("//iframe[contains(@src,'/ticket/selectSeat/')]"))</pre>



<p>selenium定位页面元素的时候会遇到定位不到的问题，明明元素就在那儿，用檢視原素也可以看到，就是定位不到，这种情况很有可能是frame在搞鬼。</p>



<p>frame标签有frameset、frame、iframe三种，frameset跟其他普通标签没有区别，不会影响到正常的定位，而frame与iframe对selenium定位而言是一样的，selenium有一组方法对frame进行操作。</p>



<h4 class="wp-block-heading">1.怎麼切到frame中(switch_to.frame())</h4>



<p>selenium提供了switch_to.frame()方法来切换frame</p>



<pre class="wp-block-preformatted">switch_to.frame(reference)</pre>



<p>reference是传入的参数，用来定位frame，可以传入id、name、index以及selenium的WebElement对象，假设有如下HTML代码 index.html：</p>



<pre class="wp-block-preformatted">&lt;html lang="en"&gt;
&lt;head&gt;
 &lt;title&gt;FrameTest&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;iframe src="a.html" id="frame1" name="myframe"&gt;&lt;/iframe&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>



<p>想要定位其中的iframe并切进去，可以通过如下代码：</p>



<pre class="wp-block-preformatted">from selenium import webdriver
driver = webdriver.Firefox()
driver.switch_to.frame(0) # 1.用frame的index来定位，第一个是0
# driver.switch_to.frame("frame1") # 2.用id来定位
# driver.switch_to.frame("myframe") # 3.用name来定位
# driver.switch_to.frame(driver.find_element_by_tag_name("iframe")) # 4.用WebElement对象来定位</pre>



<p>通常采用id和name就能够解决绝大多数问题。但有时候frame并无这两项属性，则可以用index和WebElement来定位：</p>



<p>index从0开始，传入整型参数即判定为用index定位，传入str参数则判定为用id/name定位<br>WebElement对象，即用find_element系列方法所取得的对象，我们可以用tag_name、xpath等来定位frame对象<br>举个例子：</p>



<pre class="wp-block-preformatted">&lt;iframe src="myframetest.html" /&gt;</pre>



<p>用xpath定位，传入WebElement对象：</p>



<pre class="wp-block-preformatted">driver.switch_to.frame(driver.find_element_by_xpath("//iframe[contains(@src,'myframe')]"))</pre>



<h4 class="wp-block-heading">2.從frame中切回主文件(switch_to.default_content())</h4>



<p>切到frame中之后，我们便不能继续操作主文档的元素，这时如果想操作主文档内容，则需切回主文档。</p>



<pre class="wp-block-preformatted">driver.switch_to.default_content()</pre>



<h4 class="wp-block-heading">3.iframe的操作(switch_to.parent_frame())</h4>



<p>有时候我们会遇到嵌套的frame，如下：</p>



<pre class="wp-block-preformatted">&lt;html&gt;
 &lt;iframe id="frame1"&gt;
 &lt;iframe id="frame2" / &gt;
 &lt;/iframe&gt;
&lt;/html&gt;</pre>



<p>1.從主文件切到frame2，一層層切進去</p>



<pre class="wp-block-preformatted">driver.switch_to.frame("frame1")
driver.switch_to.frame("frame2")</pre>



<p>2.從frame2再切回frame1，這裡selenium給我們提供了一個方法能夠從子frame切回到父frame，而不用我們切回主文件再切進來。</p>



<pre class="wp-block-preformatted">driver.switch_to.parent_frame() # 如果当前已是主文档，则无效果</pre>



<p>有了parent_frame()這個相當於後退的方法，我們可以隨意切換不同的frame，隨意的跳來跳去了。解法：</p>



<pre class="wp-block-preformatted">driver.switch_to.frame(reference)
driver.switch_to.parent_frame()
driver.switch_to.default_content()</pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>如何在Server side（伺服器端）檢查使用者有沒開 chromedriver？</p>



<p>Can a website detect when you are using selenium with chromedriver?<br><a href="https://stackoverflow.com/questions/33225947/can-a-website-detect-when-you-are-using-selenium-with-chromedriver">https://stackoverflow.com/questions/33225947/can-a-website-detect-when-you-are-using-selenium-with-chromedriver</a></p>



<p>上面文章不用去看了，我檢查過新的版本的 selenium 完全不會多產生上面的 key 值。</p>



<hr class="wp-block-separator has-css-opacity"/>



<p>拓元在 2018-05-12 之後更新的javascript 如下：</p>



<pre class="wp-block-preformatted">function order_check() {
 var count = valueCount(["WMeBWmQEOdoAKQq0wKU8kv4k5VcwA3GjyISDUmtPZek="]),
 maxQuota = 4;

if(!$("#TicketForm_agree").prop("checked")) {
 alert("\u8acb\u5148\u8a73\u95b1\u4e14\u540c\u610f\u6703\u54e1\u670d\u52d9\u689d\u6b3e\u5f8c\u518d\u884c\u9001\u51fa\u52d5\u4f5c\u3002");
 } else if (count &gt; maxQuota) {
 alert("\u55ae\u7b46\u4ea4\u6613\u6700\u591a\u53ef\u8cb7 \" + maxQuota + \" \u5f35");
 } else if (count == 0) {
 alert("\u8acb\u81f3\u5c11\u9078\u64c7\u4e00\u7a2e\u7968\u7a2e");
 
 } else {
 var ticketType = ["WMeBWmQEOdoAKQq0wKU8kv4k5VcwA3GjyISDUmtPZek="],
 ticketTypeSelector = $("[name=\"" + ticketType.join("\"], [name=\"") + "\"]");

ticketTypeSelector.each(function() {
 $(this).attr("name", "TicketForm[ticketPrice][" + $(this).get(0).name + "]");
 });
 return true;
 }

return false;
}

function valueCount(elements) {
 elements = countValById(elements);
 return elements.reduce(function(total, element) {
 return total + element;
 }, 0);
}

$("select[id=\"WMeBWmQEOdoAKQq0wKU8kv4k5VcwA3GjyISDUmtPZek=\"]").on("click", function(event) {
 if (!!event.originalEvent.isTrusted &amp;&amp; !event.isTrigger) {
 $("#TicketForm_checked").attr("name", "TicketForm[ticketPrice][vQmwBD+sVq5AOWaOJrdiOQ5oIjAlhU38AxsBgnL1qkU=]");
 }
});
$("#TicketForm_agree").on("click", function(event) {
 if (!!event.originalEvent.isTrusted &amp;&amp; !$(this).checked &amp;&amp; !event.isTrigger) {
 $(this).attr("name", "TicketForm[agree][YnuMm9Vok/JcdY82p5pho4QaTg8m+p735VSWpPyjOfE=]");
 }
})

$("#TicketForm").on("change", function(event) {
 var ticketType = ["WMeBWmQEOdoAKQq0wKU8kv4k5VcwA3GjyISDUmtPZek="];

if (ticketType.indexOf(event.target.id) != -1) {
 var count = valueCount(ticketType),
 maxQuota = 4;

if (count &gt; maxQuota) {
 var num = parseInt($(event.target).val()) + (maxQuota - count);

alert("\u55ae\u7b46\u4ea4\u6613\u6700\u591a\u53ef\u8cb7 \" + maxQuota + \" \u5f35\uff0c\u60a8\u5171\u9078\u64c7\u4e86 \" + count + \" \u5f35");

while ($(event.target).find("option[value=" + num + "]").length &lt; 1 &amp;&amp; num != 0) {
 num--;
 }

$(event.target).val(num);
 }

$("#ticketQuota").text(maxQuota - valueCount(ticketType));
 }
});

$("#TicketForm select").change();</pre>



<hr class="wp-block-separator has-css-opacity"/>



<pre class="wp-block-preformatted"> &lt;select class="mobile-select" name="WMeBWmQEOdoAKQq0wKU8kv4k5VcwA3GjyISDUmtPZek=" id="WMeBWmQEOdoAKQq0wKU8kv4k5VcwA3GjyISDUmtPZek="&gt;
&lt;option value="0"&gt;0&lt;/option&gt;
&lt;option value="1"&gt;1&lt;/option&gt;
&lt;option value="2"&gt;2&lt;/option&gt;
&lt;option value="3"&gt;3&lt;/option&gt;
&lt;option value="4"&gt;4&lt;/option&gt;
 &lt;/select&gt;</pre>



<p>針對上面的程式碼，如果使用</p>



<pre class="wp-block-preformatted">driver.execute_script("$('#TicketForm_agree').prop('checked', true);")</pre>



<p>並不會觸發 onclick 事件。請改服用：</p>



<pre class="wp-block-preformatted">form_checkbox = None
try:
 form_checkbox = driver.find_element(By.ID, 'TicketForm_agree')
 if form_checkbox is not None:
 try:
 form_checkbox.click()
 except Exception as exc:
 print "click TicketForm_agree fail"
 pass
except NoSuchElementException:
 print "find TicketForm_agree fail"</pre>



<p>附註， select box 比照 checkbox 的 code, 先產生 click 再去選取預期的張數即可。</p>



<hr class="wp-block-separator has-css-opacity"/>



<p>2018年09月某一天 發現拓元的 javascript 又增加了幾個新的檢查點，javascript 如下：</p>



<pre class="wp-block-preformatted">function countValById(arr) {
    return arr.map(function(val) {
        return parseInt($("[id=\"" + val + "\"]").val());
    });
}

function order_check() {
    var count = valueCount(["gqQB0FXCgar2OyOvqUFZR1xujK9R1sO+OR6V6m\/unzY="]),
        maxQuota = 4;

    if(!$("#TicketForm_agree").prop("checked")) {
        alert("\u8acb\u5148\u8a73\u95b1\u4e14\u540c\u610f\u6703\u54e1\u670d\u52d9\u689d\u6b3e\u5f8c\u518d\u884c\u9001\u51fa\u52d5\u4f5c\u3002");
    } else if (count &gt; maxQuota) {
        alert("單筆交易最多可買 " + maxQuota + " 張");
    } else if (count == 0) {
        alert("\u8acb\u81f3\u5c11\u9078\u64c7\u4e00\u7a2e\u7968\u7a2e");
    
    } else {
        var ticketType = ["gqQB0FXCgar2OyOvqUFZR1xujK9R1sO+OR6V6m\/unzY="],
            ticketTypeSelector = $("[name=\"" + ticketType.join("\"], [name=\"") + "\"]");

        ticketTypeSelector.each(function() {
            $(this).attr("name", "TicketForm[ticketPrice][" + $(this).get(0).name + "]");
        });
        return true;
    }

    return false;
}

function valueCount(elements) {
    elements = countValById(elements);
    return elements.reduce(function(total, element) {
        return total + element;
    }, 0);
}

$(document).ready(function() {
    var ticketType = ["gqQB0FXCgar2OyOvqUFZR1xujK9R1sO+OR6V6m\/unzY="],
        ticketTypeSelector = "[id='" + ticketType.join("'], [id='") + "']";

    $("#TicketForm_agree").attr("name", "TicketForm[agrees]");
    $("#TicketForm_checked").attr("name", "TicketForm[ticketPrice][checks][ + $(ticketTypeSelector).length + ]");

    ravenCheck(ticketTypeSelector);

    $("#TicketForm").on("mousedown click touchstart", ticketTypeSelector, function(event) {
        $("#TicketForm_checked").attr("name", "s_" + event.originalEvent.isTrusted + "_" + event.isTrigger);
        if (event.originalEvent.isTrusted !== false &amp;&amp; !event.isTrigger) {
            $("#TicketForm_checked").attr("name", "TicketForm[ticketPrice][5BQBWTBCQoAEPama/ehw8qJhA1lkdF0fH8J5eua5HSw=]");
        }
    }).on("mousedown click touchstart", "#TicketForm_agree", function(event) {
        $(this).attr("name", "s_" + event.originalEvent.isTrusted + "_" + event.isTrigger);
        if (event.originalEvent.isTrusted !== false &amp;&amp; !$(this).checked &amp;&amp; !event.isTrigger) {
            $(this).attr("name", "TicketForm[agree][Dbk4t/2b/yoQPK0qAnhBljhX0JBLgehzAlwuEOBdEik=]");
        }
    }).on("change", function(event) {
        if (ticketType.indexOf(event.target.id) != -1) {
            var count = valueCount(ticketType),
                maxQuota = 4;

            if (count &gt; maxQuota) {
                var num = parseInt($(event.target).val()) + (maxQuota - count);

                alert("單筆交易最多可買 " + maxQuota + " 張，您共選擇了 " + count + " 張");

                while ($(event.target).find("option[value=" + num + "]").length &lt; 1 &amp;&amp; num != 0) {
                    num--;
                }

                $(event.target).val(num);
            }

            $("#ticketQuota").text(maxQuota - valueCount(ticketType));
        }
    });

    $("#TicketForm select").change();
});

jQuery(document).on('click', '#yw0', function(){
    jQuery.ajax({
        url: "\/ticket\/captcha?refresh=1",
        dataType: 'json',
        cache: false,
        success: function(data) {
            jQuery('#yw0').attr('src', data['url']);
            jQuery('body').data('captcha.hash', [data['hash1'], data['hash2']]);
        }
    });
    return false;
});</pre>



<hr class="wp-block-separator has-css-opacity"/>



<h4 class="wp-block-heading">event.originalEvent.isTrusted</h4>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Event 介面的 isTrusted 唯讀屬性為一個布林值，若事件物件是由使用者操作而產生，則 isTrusted 值為 true。若事件物件是由程式碼所建立、修改，或是透過 EventTarget.dispatchEvent() 來觸發，則 isTrusted 值為 false。</p>
</blockquote>



<h4 class="wp-block-heading">Event.isTrusted</h4>



<p>The&nbsp;<code>isTrusted</code>&nbsp;read-only property of the&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/API/Event"><code>Event</code></a>&nbsp;interface is a&nbsp;<code>Boolean</code>&nbsp;that is&nbsp;<code>true</code>when the event was generated by a user action such as mouse click, and&nbsp;<code>false</code>&nbsp;when the event was scripted or invoked via&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent"><code>dispatchEvent</code></a>.</p>



<p>This new property is intended primarily for use by browser extensions, to determine if an event was dispatched by a script running in the main world or not.</p>



<p>如果單純使用之前的程式，會讓&nbsp;$(&#8220;#TicketForm_checked&#8221;).attr(&#8220;name&#8221;); 取得的結果為：</p>



<pre class="wp-block-preformatted">s_false_undefined</pre>



<p>然後會造成搶票失敗，帳號會被登出。解法：</p>



<p>其實大多的情況下&nbsp;Selenium 讓&nbsp;Event.isTrusted 的結果是 True，調整一下網頁裡事件的執行順序就解決了，拓元很難透過網頁檢測是使用者透過機器人來輔助買票，如果你寫的程式可以被驗測到，代表調整一下順序應該就可以跳過檢查。</p>



<hr class="wp-block-separator has-css-opacity"/>



<p>上面對很多沒學過 javascript 的應該看起來像是火星文，建議先學一下簡單的 javascript 和 jQuery.</p>



<p>不能確定下次開演唱會時，Max的搶票程式是否可以使用，因為拓元定期會改版。</p>



<p>selenium 的程式有一些限制，必需先知道：</p>



<ul class="wp-block-list">
<li>1：會開出新的「視窗」，所以需要重新登入帳號。</li>



<li>2：不能使用新的「分頁」，程式只能控制第一個分頁，所以建議你開2～3個 selenium，放在背景，而且先都登入好會員，如果第一個視窗在搶票時遇到圈圈狂轉，這時候趕快派2號視窗上場救援。<br>（附註：其實是可以控制其他分頁，會比較麻煩一點，難度也會比較高，只處理第一個分頁會簡單很多。）</li>



<li>3：想看我的程式可以匯錢給我，歡迎與我聯絡：<a href="mailto:weng.32002@gmail.com">weng.32002@gmail.com</a></li>
</ul>



<hr class="wp-block-separator has-css-opacity"/>



<p>自動關掉 alert 對話框的工具：<br><a href="https://chrome.google.com/webstore/detail/alert-control/ofjjanaennfbgpccfpbghnmblpdblbef">https://chrome.google.com/webstore/detail/alert-control/ofjjanaennfbgpccfpbghnmblpdblbef</a></p>



<p>如果有討人厭的alert 彈出式的javascript 語法，可以節省大約一秒的時間。</p>



<p>要下載 chrome extension 可以使用 &#8220;Get CRX&#8221; extension 來取得：<br><a href="https://chrome.google.com/webstore/detail/get-crx/dijpllakibenlejkbajahncialkbdkjc">https://chrome.google.com/webstore/detail/get-crx/dijpllakibenlejkbajahncialkbdkjc</a></p>



<hr class="wp-block-separator has-css-opacity"/>



<p>在 selenium 裡載入 extension 程式碼：</p>



<pre class="wp-block-preformatted">extension_path = Root_Dir + "webdriver/Alert_Control.crx"
chrome_options = webdriver.ChromeOptions()
chrome_options.add_extension(extension_path)
chromedriver_path =Root_Dir+ "webdriver/chromedriver"
driver = webdriver.Chrome(chrome_options=chrome_options, executable_path=chromedriver_path)</pre>



<hr class="wp-block-separator has-css-opacity"/>



<p>Q：Selenium 支持那些程式語言？<br>A：參考看看<a href="https://www.selenium.dev/downloads/">https://www.selenium.dev/downloads/</a></p>



<ul class="wp-block-list">
<li>Ruby</li>



<li>Java</li>



<li>Python</li>



<li>C#</li>



<li>JavaScript</li>
</ul>



<hr class="wp-block-separator has-css-opacity"/>



<p>當人們在網站註冊或購物時，經常會出現圖像驗證碼的輸入要求，為了區分「真人」與「機器人」，圖片會出現線條及扭曲分隔開的文字，讓電腦程式的機器人難以辨識，目前Max的搶票機器人沒有辦法處理「驗證碼」的部份，需要人工去輸入，機器人幫忙處理其他的欄位的輸入。</p>



<p>人外有人，天外有天，驗證碼的部份應該也可以透過程式識別，識別也是有分難度的，簡單的驗證碼可以透過去切割圖片，再把切割好的圖片採用深度學習（Deep learning）的方式去訓練就可以有效提升識別率。難一點的驗證碼就是字元會變形、重疊還有雜訊。拓元網站是屬於中上等級，只有變形和重疊。</p>



<p>沒有推薦的實作方向，因為我也沒有研究過。</p>



<hr class="wp-block-separator has-css-opacity"/>



<h4 class="wp-block-heading">相關文章：</h4>



<p>Max的拓元搶票機器人<br><a href="http://max-everyday.com/2018/03/tixcraft-bot/">http://max-everyday.com/2018/03/tixcraft-bot/</a></p>



<p>Max自動掛號機器人<br><a href="http://max-everyday.com/2018/08/max-auto-reg-bot/">http://max-everyday.com/2018/08/max-auto-reg-bot/</a></p>



<p>Max 學習 tkinter：<br><a href="https://stackoverflow.max-everyday.com/tag/tkinter/">https://stackoverflow.max-everyday.com/tag/tkinter/</a></p>



<p>Max 學習 selenium：<br><a href="https://stackoverflow.max-everyday.com/tag/selenium/">https://stackoverflow.max-everyday.com/tag/selenium/</a></p>



<p>[Python] 如何取出字串中的選項<br><a href="https://stackoverflow.max-everyday.com/2018/12/python-regular-expression-findall/">https://stackoverflow.max-everyday.com/2018/12/python-regular-expression-findall/</a><br>這篇文章目是透過程式取得「驗證問題」裡的選項，再用程式來自動把選項用來回答問題。</p>



<p>實作基於CNN的台鐵訂票驗證碼辨識以及透過模仿及資料增強的訓練集產生器<br>(Simple captcha solver based on CNN and a training set generator by imitating the style of captcha and data augmentation)<br><a href="https://github.com/JasonLiTW/simple-railway-captcha-solver">https://github.com/JasonLiTW/simple-railway-captcha-solver</a><br></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2018/03/selenium-chrome-webdriver/feed/</wfw:commentRss>
			<slash:comments>82</slash:comments>
		
		
			</item>
		<item>
		<title>How do you turn off auto-capitalisation in HTML form fields in iOS?</title>
		<link>https://stackoverflow.max-everyday.com/2017/09/how-do-you-turn-off-auto-capitalisation-in-html-form-fields-in-ios/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/09/how-do-you-turn-off-auto-capitalisation-in-html-form-fields-in-ios/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 19 Sep 2017 07:23:25 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[iOS]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=1362</guid>

					<description><![CDATA[Since iOS 5, type="email...]]></description>
										<content:encoded><![CDATA[<p>Since iOS 5, <code>type="email"</code> has auto-capitalization disabled automatically, so you simply need:</p>
<pre class="default prettyprint prettyprinted"><code><span class="tag">&lt;input</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"email"</span><span class="tag">&gt;</span></code></pre>
<p>For other input types, there are attributes available that do what they say:</p>
<pre class="default prettyprint prettyprinted"><code><span class="tag">&lt;input</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span> <span class="atn">autocorrect</span><span class="pun">=</span><span class="atv">"off"</span> <span class="atn">autocapitalize</span><span class="pun">=</span><span class="atv">"none"</span><span class="tag">&gt;</span></code></pre>
<p>If for some reason you want to support iOS prior to version 5, use this for <code>type="email"</code>:</p>
<pre class="default prettyprint prettyprinted"><code><span class="tag">&lt;input</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"email"</span> <span class="atn">autocorrect</span><span class="pun">=</span><span class="atv">"off"</span> <span class="atn">autocapitalize</span><span class="pun">=</span><span class="atv">"none"</span><span class="tag">&gt;</span></code></pre>
<p>More information:</p>
<ul>
<li><a href="https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/Attributes.html#//apple_ref/doc/uid/TP40008058-autocapitalize">iOS Documentation</a></li>
<li><a href="http://sja.co.uk/2012/1/4/controlling-which-ios-keyboard-is-shown">Controlling which iOS keyboard is shown</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/09/how-do-you-turn-off-auto-capitalisation-in-html-form-fields-in-ios/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>sublime html encode</title>
		<link>https://stackoverflow.max-everyday.com/2017/09/sublime-html-encode/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/09/sublime-html-encode/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Wed, 06 Sep 2017 06:07:17 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[sublime]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=1251</guid>

					<description><![CDATA[上次使用 sublime 幫 java 的 so...]]></description>
										<content:encoded><![CDATA[<p>上次<a href="https://stackoverflow.max-everyday.com/2017/08/sublime-text-sublimeastyleformatter/">使用 sublime 幫 java 的 source code format</a> 效果很好，這次希望 sublime 可以幫我做html encode。</p>
<h4>SublimeAStyleFormatter Plugin  的安裝方式：</h4>
<p>用 Package Install 來安裝～</p>
<p>Sublime Text &gt; Tools &gt; Command Palette &gt; Package Control: Install Package，</p>
<p>找到 StringEncode 安裝～</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1252" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/09/Screenshot-2017-09-06-13.59.54.jpg" alt="" width="800" height="202" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/09/Screenshot-2017-09-06-13.59.54.jpg 800w, https://stackoverflow.max-everyday.com/wp-content/uploads/2017/09/Screenshot-2017-09-06-13.59.54-600x152.jpg 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2017/09/Screenshot-2017-09-06-13.59.54-768x194.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></p>
<p>&nbsp;</p>
<p>You can use more functional plugin <a href="https://github.com/colinta/SublimeStringEncode" rel="nofollow">SublimeStringEncode</a>.</p>
<ol>
<li>Install it using Package Control, type &#8220;StringEncode&#8221;.</li>
<li><kbd>cmd</kbd> + <kbd>shift</kbd> + <kbd>P</kbd> then 在輸入框裡輸 &#8220;HTML entitize&#8221; 就可以看到 StringEncode 提供的function，超神奇，好好用的。</li>
</ol>
<hr />
<p>In addition you will have some other useful commands:</p>
<ul>
<li><code>html_deentitize</code>: Converts HTML entities to a character</li>
<li><code>url_encode</code>: Uses urllib.quote to escape special URL characters</li>
<li><code>url_decode</code>: Uses urllib.unquote to convert escaped URL characters</li>
<li><code>json_escape</code>: Escapes a string and surrounds it in quotes, according to the JSON encoding.</li>
<li><code>json_unescape</code>: Unescapes a string (include the quotes!) according to JSON encoding.</li>
<li><code>base64_encode</code>: Uses base64 to encode into base64</li>
<li><code>base64_decode</code>: Uses base64 to decode from base64</li>
<li><code>md5_encode</code>: Uses sha package to create md5 hash</li>
<li><code>sha256_encode</code>: Uses sha package to create sha256 hash</li>
<li><code>sha512_encode</code>: Uses sha package to create sha512 hash</li>
<li><code>escape_regex</code>: Escapes regex meta characters</li>
<li><code>escape_like</code>: Escapes SQL-LIKE meta characters</li>
<li><code>safe_html_entitize</code>: Converts characters to their HTML entity, but preserves HTML reserved characters</li>
<li><code>safe_html_deentitize</code>: Converts HTML entities to a character, but preserves HTML reserved characters</li>
<li><code>xml_entitize</code>: Converts characters to their XML entity</li>
<li><code>xml_deentitize</code>: Converts XML entities to a character</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/09/sublime-html-encode/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How can I debug a HTTP POST in Chrome / Firefox?</title>
		<link>https://stackoverflow.max-everyday.com/2017/08/how-can-i-debug-a-http-post-in-chrome-firefox/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/08/how-can-i-debug-a-http-post-in-chrome-firefox/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 15 Aug 2017 08:13:22 +0000</pubDate>
				<category><![CDATA[電腦相關應用]]></category>
		<category><![CDATA[html]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=1085</guid>

					<description><![CDATA[原來要看到browser post 的資料，還滿...]]></description>
										<content:encoded><![CDATA[<p>原來要看到browser post 的資料，還滿簡單的耶！好方便哦。</p>
<hr />
<p>Firefox截圖：</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1086" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/08/Screenshot-2017-08-15-16.10.59.jpg" alt="" width="640" height="249" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/08/Screenshot-2017-08-15-16.10.59.jpg 640w, https://stackoverflow.max-everyday.com/wp-content/uploads/2017/08/Screenshot-2017-08-15-16.10.59-600x233.jpg 600w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<hr />
<p>Go to Chrome Developer Tools (Chrome Menu -&gt; More Tools -&gt; Developer Tools). Choose &#8220;Network&#8221; tab. Refresh the page you&#8217;re on. You&#8217;ll get list of http queries that happened, while the network console was on. Select one of them in the left. Choose &#8220;Headers&#8221; tab. Voila!</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/08/how-can-i-debug-a-http-post-in-chrome-firefox/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>jQuery動態新增多組記錄</title>
		<link>https://stackoverflow.max-everyday.com/2017/08/jquery-dymanic-add-rows/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/08/jquery-dymanic-add-rows/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 15 Aug 2017 07:06:38 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[Java筆記]]></category>
		<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=1079</guid>

					<description><![CDATA[分享如何在同一個畫面裡讓使用者可以無限制新增多筆...]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1080" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/08/Screenshot-2017-08-15-14.14.17.png" alt="" width="640" height="256" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2017/08/Screenshot-2017-08-15-14.14.17.png 640w, https://stackoverflow.max-everyday.com/wp-content/uploads/2017/08/Screenshot-2017-08-15-14.14.17-600x240.png 600w" sizes="(max-width: 640px) 100vw, 640px" /></p>
<p>分享如何在同一個畫面裡讓使用者可以無限制新增多筆記錄。</p>
<p>上面的畫面中，使用了我沒學過bootstrap技術，為了要讓右邊多一個button, 要記得pull-right 一下，參考這篇：<br />
<a href="https://stackoverflow.max-everyday.com/2017/08/bootstrap-panel-header-with-buttons-on-right-side/">https://stackoverflow.max-everyday.com/2017/08/bootstrap-panel-header-with-buttons-on-right-side/</a></p>
<p>要完成這個功能，需要在 &lt;form&gt; tag 外放把 row 放到隱藏的div裡：</p>
<pre>&lt;div id="phoeniixx_discount_div" style="display:none;"&gt;
 &lt;div class="phoeniixx_discount_min_max_div"&gt;
 &lt;input type="number" placeholder="Min Quantity" name="min_val[]"  class="min_val" value=""&gt;
 &lt;input type="number"  placeholder="Max Quantity" name="max_val[]" class="max_val" value=""&gt;
 &lt;input type="number" step='any' placeholder="Discount Value" name="discount[]" class="discount" value=""&gt;
 &lt;button name="remove_b" class="phoe_remove_disc_div button"&gt;-&lt;/button&gt; &lt;/div&gt;
&lt;/div&gt;</pre>
<hr />
<p>找一個 div 當容器：</p>
<pre>&lt;div class="phoeniixx_discount_html_content_div"&gt;&lt;/div&gt;</pre>
<hr />
<p>新增的jQuery:</p>
<pre>var a = jQuery('#phoeniixx_discount_div').html();
jQuery('.phoe_add_disc_more').click(function(){ jQuery('.phoeniixx_discount_html_content_div').append(a);});</pre>
<hr />
<p>刪除的jQuery:</p>
<pre>jQuery(document).on('click','.phoe_remove_disc_div',function(){jQuery(document).on('click','.phoe_remove_disc_div',function(){ jQuery(this).parent('div').remove();});</pre>
<hr />
<p>Source code 下載：<br />
<a href="https://tw.wordpress.org/plugins/dynamic-price-and-discounts-for-woocommerce/">https://tw.wordpress.org/plugins/dynamic-price-and-discounts-for-woocommerce/</a></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/08/jquery-dymanic-add-rows/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Form is submitted when I click on the button in form. How to avoid this?</title>
		<link>https://stackoverflow.max-everyday.com/2017/08/form-is-submitted-when-i-click-on-the-button-in-form-how-to-avoid-this/</link>
					<comments>https://stackoverflow.max-everyday.com/2017/08/form-is-submitted-when-i-click-on-the-button-in-form-how-to-avoid-this/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 15 Aug 2017 06:02:45 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[Java筆記]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[html]]></category>
		<guid isPermaLink="false">http://stackoverflow.max-everyday.com/?p=1077</guid>

					<description><![CDATA[原來button 沒加 type 屬性，會變成 ...]]></description>
										<content:encoded><![CDATA[<p>原來button 沒加 type 屬性，會變成 submit @_@;</p>
<p>太久沒寫網頁，這個變化真大。</p>
<hr />
<p>From the fine <a href="http://www.w3.org/TR/html-markup/button.html">HTML5 specification</a>:</p>
<blockquote><p>A <em>button</em> element with no <em>type</em> attribute specified represents the same thing as a button element with its type attribute set to <em>&#8220;submit&#8221;</em>.</p></blockquote>
<p>And a <a href="http://www.w3.org/TR/html-markup/button.submit.html#button.submit"><code>&lt;button type="submit"&gt;</code></a> submits the form rather than behaving like a simple <a href="http://www.w3.org/TR/html-markup/button.button.html#button.button"><code>&lt;button type="button"&gt;</code> push-button</a>.</p>
<p>The <a href="http://www.w3.org/TR/html4/interact/forms.html#h-17.5">HTML4 spec</a> says the same thing:</p>
<blockquote><p><strong>type = submit|button|reset</strong> [CI]<br />
This attribute declares the type of the button. Possible values:</p>
<ul>
<li><code>submit</code>: Creates a submit button. This is the default value.</li>
<li><code>reset</code>: Creates a reset button.</li>
<li><code>button</code>: Creates a push button.</li>
</ul>
</blockquote>
<p>So your <code>&lt;button&gt;</code> elements:</p>
<pre class="default prettyprint prettyprinted"><code><span class="tag">&lt;button</span> <span class="atn">class</span><span class="pun">=</span><span class="atv">"btn"</span><span class="tag">&gt;</span><span class="pln">Button_1</span><span class="tag">&lt;/button&gt;</span>
<span class="tag">&lt;button</span> <span class="atn">class</span><span class="pun">=</span><span class="atv">"btn"</span><span class="tag">&gt;</span><span class="pln">Button_2</span><span class="tag">&lt;/button&gt;</span></code></pre>
<p>are the same as these (in compliant browsers):</p>
<pre class="default prettyprint prettyprinted"><code><span class="tag">&lt;button</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span> <span class="atn">class</span><span class="pun">=</span><span class="atv">"btn"</span><span class="tag">&gt;</span><span class="pln">Button_1</span><span class="tag">&lt;/button&gt;</span>
<span class="tag">&lt;button</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span> <span class="atn">class</span><span class="pun">=</span><span class="atv">"btn"</span><span class="tag">&gt;</span><span class="pln">Button_2</span><span class="tag">&lt;/button&gt;</span></code></pre>
<p>and any time you hit one of those buttons you&#8217;ll submit your form.</p>
<p>The solution is to use plain buttons:</p>
<pre class="default prettyprint prettyprinted"><code><span class="tag">&lt;button</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"button"</span> <span class="atn">class</span><span class="pun">=</span><span class="atv">"btn"</span><span class="tag">&gt;</span><span class="pln">Button_1</span><span class="tag">&lt;/button&gt;</span>
<span class="tag">&lt;button</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"button"</span> <span class="atn">class</span><span class="pun">=</span><span class="atv">"btn"</span><span class="tag">&gt;</span><span class="pln">Button_2</span><span class="tag">&lt;/button&gt;</span></code></pre>
<p>Some versions of IE default to <code>type="button"</code> despite what the standard says. You should always specify the <code>type</code> attribute when using a <code>&lt;button&gt;</code> just to be sure that you will get the behavior you&#8217;re expecting.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2017/08/form-is-submitted-when-i-click-on-the-button-in-form-how-to-avoid-this/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
