<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anak Mirasing</title>
    <description>The latest articles on DEV Community by Anak Mirasing (@igroomgrim).</description>
    <link>https://dev.to/igroomgrim</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F299807%2Fc7adfd29-25f7-42f8-8e36-a1a2aa04f532.png</url>
      <title>DEV Community: Anak Mirasing</title>
      <link>https://dev.to/igroomgrim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igroomgrim"/>
    <language>en</language>
    <item>
      <title>Common types of bugs - บั๊กทั่วๆไป มีอะไรบ้างหนอ?</title>
      <dc:creator>Anak Mirasing</dc:creator>
      <pubDate>Mon, 06 Jul 2020 16:50:30 +0000</pubDate>
      <link>https://dev.to/igroomgrim/common-types-of-bugs-5830</link>
      <guid>https://dev.to/igroomgrim/common-types-of-bugs-5830</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;บั๊ก คือ อะไร?&lt;/strong&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction 🙋‍♂️
&lt;/h2&gt;

&lt;p&gt;ในโลกของซอฟท์แวร์ ไม่ว่าจะโปรแกรมเมอร์มือใหม่ มือเก่า มือเก๋า หรือแม้แต่สุดยอดโปรแกรมเมอร์ ต่างก็เคยสร้างข้อผิดพลาดทางโปรแกรมกันทั้งนั้น เราๆเองก็มักจะเรียกข้อผิดพลาดเหล่านั้นว่า "Bug(บั๊ก)".&lt;/p&gt;

&lt;h2&gt;
  
  
  Common types of bugs 🐞
&lt;/h2&gt;

&lt;p&gt;โดยทั่วไปแล้ว เรามักจะแบ่งชนิดของบั๊กเป็นกลุ่มใหญ่ๆ 3 กลุ่มหลักๆ&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Syntax errors&lt;/li&gt;
&lt;li&gt;Logic errors &lt;/li&gt;
&lt;li&gt;Runtime errors&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Syntax errors 🙊
&lt;/h2&gt;

&lt;p&gt;น้องเล็ก... Syntax errors ถือว่าเป็นน้องเล็กของวงการละกัน เพราะเค้าจะง่ายในการตามหาอย่างเช่น การสะกดชื่อตัวแปร, ชื่อฟังก์ชั่น, ชื่อคลาสผิด หรือการใช้สัญลักษณ์พิเศษหรืออาจเผลอไปเอา Reserved word(คำสงวน) มาใช้เป็นชื่อตัวแปร หรือคลาส โดยส่วนใหญ่แล้ว Compiler หรือ IDE ที่เหล่านักพัฒนาใช้ในปัจจุบัน มักจะช่วยตรวจสอบ Syntax errors ได้ดีพอสมควร อย่างเช่น แจ้งให้เราทราบว่า เราเรียกใช้ตัวแปรที่ยังไม่ได้ประกาศ ฟังก์ชั่นนี้ยังไม่ได้สร้างนะ หรือถึงขั้นแนะนำได้ว่า เราอยากจะเรียกใช้ตัวแปรหรือฟังก์ชั่นนี้ใช่หรือไม่ อาจมีทั้งไฮไลท์หรือ pop-up menu ให้เราใช้อย่างเสร็จสรรพ ทำให้เราตามหาเจ้าน้องเล็กได้ง่ายขึ้นนั่นเอง&lt;/p&gt;

&lt;h2&gt;
  
  
  Logic errors 🙉
&lt;/h2&gt;

&lt;p&gt;พี่คนกลาง... Logic errors นี่เก๋าขึ้นมาหน่อย เพราะส่วนใหญ่มักรอดจากการเป็นน้องเล็กมาแล้ว โค้ดตรงนี้ก็พิมพ์ถูกนี่นา รันโปรแกรมก็ได้ปกติ แต่ทำไมค่าตรงนี้มันคำนวณคำตอบมาผิดซะงั้น? เพราะปัญหาของ Logic errors เครื่องมือส่วนใหญ่ที่เราใช้เขียนโปรแกรมมันแทบจะหาไม่เจอเลยก็ว่าได้ แต่ยังโชคดีที่แทบจะ 100% ของ Logic errors นั้น เราสามารถที่จะหามันเจอได้จากโค้ดที่เราเขียนขึ้นมาเองนี่แหละ เพราะเค้าเกิดจากการทำงานที่ไม่ตรงกับความต้องการของเรานั่นเอง อย่างเช่น เราต้องการที่จะให้คำนวณส่วนลด 10% ให้ลูกค้าเมื่อมีการซื้อสินค้าครบ 1,000 บาท แต่เมื่อลูกค้าซื้อครบ 1,000 แล้วโปรแกรมกลับไม่คำนวณส่วนลดให้ซะงั้น ตรงนี้เอง เราจะสามารถ "เดา" หรือ "คาดการ" ได้ว่า มันเกิดขึ้นที่ตัวแปร, ฟังก์ชั่นหรือส่วนไหนของโปรแกรมที่เราเขียน เราค่อยเข้าไปแก้ไขและทดสอบในส่วนนั้นๆของโปรแกรมได้&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime errors 🙈
&lt;/h2&gt;

&lt;p&gt;พี่ใหญ่... Runtime errors คนนี้เค้าเก๋าสุด เข้มสุดเลยก็ว่าได้บางที นักพัฒนาหลายๆคนอาจเคยเจอปัญหาแบบ เอ๊ะ รันใน iPhone ก็ได้ปกตินี่หว่า ทำไมรันใน iPad เปิดหน้านี้ทีไร Crash หรือเด้งออกทุกที หรือบางคนอาจเคยได้ยินคำว่า &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It works on my machine" &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ก็มันรันบนเครื่องฉันได้ปกติหนิ ทำไมไปรันบนเครื่องอื่นแล้วมันเจ๊ง มันเจ๊งได้ไงฟร๊ะ นั่นจึงเป็นสาเหตุว่าทำไม พี่ใหญ่เขาถึงเก๋าสุดเข้มสุด เพราะเหล่านักพัฒนาอาจต้องมองกว้างขึ้น ลึกขึ้นหรือลงรายละเอียดเข้าไปถึงหลายๆอย่าง เช่นสภาพแวดล้อมของระบบที่ใช้รันโปรแกรม ขนาดของเมมโมรี, เวอร์ชั่นของระบบปฏิบัติการ, ความเสถียรของอินเตอร์เน็ต, ฮาร์ดแวร์ของเครื่องที่ใช้และอื่นๆอีกมากมาย หลายต่อหลายครั้งในเหตุการณ์ของ Runtime errors จึงต้องอาศัยประสบการณ์ในการแก้ปัญหาพอสมควร ถึงจะหาสาเหตุที่มาของปัญหาและจัดการกับมันได้ในที่สุด&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion 🌾
&lt;/h2&gt;

&lt;p&gt;แม้ในบางครั้ง เราจะจัดการกับน้องเล็ก(Syntax errors) พี่คนกลาง(Logic errors) ได้อย่างอยู่หมัด แต่มันไม่ง่ายเลยจริงๆที่จะกล้าพูดว่าฉันจัดการพี่ใหญ่(Runtime errors) ได้ 100%!! เรียบร้อยแล้ว&lt;br&gt;
ซึ่งทางที่ดีที่สุดสำหรับนักพัฒนาอย่างเราๆแล้ว ก็ควรสละเวลาอันมีค่าไปเขียน "Test" ดีกว่าเอาเวลามาไล่หา "Bug" เพื่อให้เกิดคำว่า error-free มีอยู่จริง ต่อให้ไม่ 100% ก็ขอให้เป็น 99% ก็ยังดีครับ &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ที่ใดมี "โค้ด" ที่นั่นมี "บั๊ก"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;ก่อนจากกัน...ฝากกดไลท์ กดแชร์เพจโปรแกรมมิ่งสนุกๆไว้ให้ติดตามผ่านทาง Facebook ไว้เรียนรู้ไปด้วยกันครับ&lt;br&gt;
&lt;a href="https://www.facebook.com/igroomgrimonthefloor/" rel="noopener noreferrer"&gt;https://www.facebook.com/igroomgrimonthefloor/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;อยากให้ทุกคนสนุกกับการเขียนโค้ด&lt;br&gt;
Be lazy &amp;amp; Happy Coding 🤤🖥🤗&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>bug</category>
    </item>
    <item>
      <title>Simply Sneaker Bot with Playwright - มาลองเขียนบอทง่ายๆตามสไตล์คนขี้เกียจกันเถอะ</title>
      <dc:creator>Anak Mirasing</dc:creator>
      <pubDate>Wed, 01 Jul 2020 13:23:38 +0000</pubDate>
      <link>https://dev.to/igroomgrim/simply-sneaker-bot-with-playwright-48h2</link>
      <guid>https://dev.to/igroomgrim/simply-sneaker-bot-with-playwright-48h2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;เพราะฉัน "ขี้เกียจ" ฉันเลย "เขียนโค้ด"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction 😇
&lt;/h2&gt;

&lt;p&gt;หากเล่าถึงความขี้เกียจนั้น หลายๆคนคงเข้าใจความรู้สึกนี้ดีโดยไม่ต้องอธิบายอะไรเลยแม้แต่น้อย เราเกิดมาในยุคที่บางครั้งผู้ใหญ่จะสอนเราว่า "อย่าขี้เกียจนะ มันไม่ดี" ทั้งๆที่บางครั้งก็ควรจะปล่อยให้เป็นตามธรรมชาติบ้าง คือบางทีเราเหนื่อยมาทั้งวันละ พรุ่งนี้ขอขี้เกียจหน่อย ตื่นสายๆ นอนกลิ้งไปมาเพลินๆ ไม่มีอะไรเสียหายหนิ ถ้าทุกอย่างจบที่คำว่า "ขี้เกียจ...แต่พอดี" ซึ่งบทความนี้ มันก็เกิดจากความขี้เกียจนี่แหละ ที่ทำให้เราต้องสร้างเครื่องทุ่นแรง เราจะได้มีเวลาไปขี้เกียจ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idea 👟
&lt;/h2&gt;

&lt;p&gt;ในโลกของ Sneaker นั้น รองเท้าสวยๆถือเป็นไอเท็มที่เหล่านักสะสมต้องแย่งกันมีไว้ครอบครอง รุ่นนี้จะออกวันไหน รุ่นนั้น collab กับใคร ตัวนี้อย่างเด็ด ซึ่งความต้องการเหล่านี้ทำให้ราคารีเซลรองเท้าบางรุ่นนั้น วิ่งพรวดขึ้นไปถึง 10 - 20 เท่า!ของราคาเดิมในวันเปิดตัว เลยเป็นที่มาของโจทย์ที่ว่า จะทำยังไงดีน้า ขี้เกียจลุกขึ้นมากดแข่งกับชาวบ้านตอน 9 โมงเช้าจริงๆ กดก็ได้บ้างไม่ได้บ้าง นก(วืด)นี่คือประจำ กว่าจะเลื่อนเม้าส์ไปกด, กรอกนู่นนี่, ใส่รหัสบัตรเครดิต, กดยืนยัน หมดพลังงานไปไม่น้อยเลยทีเดียว.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding solution 🤔
&lt;/h2&gt;

&lt;p&gt;มีอะไรบ้างที่ จะมากดซื้อรองเท้าให้เราได้ในตอนเช้าๆ&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;จ้างคนอื่นกด&lt;/li&gt;
&lt;li&gt;ให้คนที่บ้านช่วยกด&lt;/li&gt;
&lt;li&gt;เขียนบอทมากด&lt;/li&gt;
&lt;li&gt;ไม่กด รวยแล้วรอซื้อราคารีเซลแม่มม &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;แน่นอน เรายังไม่รวยพอ เราเป็นโปรแกรมเมอร์เราก็ต้องเขียนบอทมาช่วยกดสิ เราก็หาๆ Solution ซึ่งมันก็มีเยอะมากเลย แต่ในบทความนี้ผมขอเลือกเล่าวิธีน่ารักๆ ง่ายๆ โดยเราจะใช้พวก Browser Automation Framework มาช่วยเราสร้าง Bot ในการช๊อปปิ้งครั้งนี้&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: บทความนี้ขอไม่เล่าถึงการเอา Proxy มาช่วย, การเจาะ iframe หน้าจ่ายเงิน, การหาที่ตั้ง server รองเท้า, การ Gen Cookies, การสู้กับ Captcha, Bot Protection และอื่นๆ บลาๆ นะครับ&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;และแล้วก็เจอ &lt;strong&gt;Playwright&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Playwright&lt;/strong&gt; คือ Browser Automation Framework ตัวนึง มีความสามารถทำ Automate testing, Web Scraping, Automating tasks, Take Screenshot, and more. ซึ่ง Playwright เนี่ย จริงๆมันก็ถูกสร้างขึ้นด้วยทีมลีดเดียวกับที่สร้าง Puppeteer นะ เพียงแต่ย้ายมาอยู่ฝั่ง Microsoft จากเดิมที่อยู่กับ Puppeteer ที่เป็นของ Google ตัว Playwright เองมันมีความได้เปรียบกว่าตรงที่มันมี cross-browser support คือมันรองรับทั้ง WebKit, Firefox และ Chromium &lt;/p&gt;

&lt;p&gt;Playwright เองมันก็เหมาะกับการเอามาทำ automate กับพวก Single Page Apps, Progressive Web Apps เพราะความสามารถจำพวก Auto-wait for element, Intercept network activity, Native input events แบบเม้าคลิก, พิมพ์นู่นนี่, หรือกดปุ่มต่างๆบนคีย์บอร์ดได้รวมทั้งอีกหลายอย่างครับ แต่จากพลังที่กล่าวมาน่าจะเพียงพอสำหรับการสร้าง Bot มากด &amp;amp; กรอก แทนเราในตอนเช้าตรู่ได้แล้ว&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites 🧰
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Knowledge of Javascript(Node.js)&lt;/li&gt;
&lt;li&gt;Web Scraping Skill&lt;/li&gt;
&lt;li&gt;Web Elements Digging Skill (Can I call "Debugging?")&lt;/li&gt;
&lt;li&gt;Lazy Skill&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Automation steps 🤖
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Login&lt;/li&gt;
&lt;li&gt;Go to item page&lt;/li&gt;
&lt;li&gt;Wait for shoe size displayed&lt;/li&gt;
&lt;li&gt;Select shoe size (by Click)&lt;/li&gt;
&lt;li&gt;Click Buy item
---- &lt;em&gt;Example End Here&lt;/em&gt; ----&lt;/li&gt;
&lt;li&gt;Wait for the Payment page (Checkout page)&lt;/li&gt;
&lt;li&gt;Input CVV &amp;amp; Credit card detail&lt;/li&gt;
&lt;li&gt;Click Continue button&lt;/li&gt;
&lt;li&gt;Click Checkout button&lt;/li&gt;
&lt;li&gt;Wish me luck!&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Coding 💻
&lt;/h2&gt;

&lt;p&gt;มาลุยยยยยกันเลยยย!&lt;br&gt;
1.มาสร้าง folder ไว้เก็บโค้ดกันก่อน เปิด Terminal เอาตั้งแต่ต้นเลยละกัน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mkdir&lt;/span&gt; &lt;span class="nx"&gt;lazy_shopping_bot&lt;/span&gt;
&lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;lazy_shopping_bot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.สร้าง package.json file ต่อเลย ตรงนี้ก็ใส่รายละเอียดของโปรเจคตามใจเราได้เลยนะ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3.ทำการ install Playwright ลงในโปรเจคของเรา ตรงนี้รอนิดนึง เพราะมันจะโหลดพวก Chromium, Firefox, WebKit engine รอแป๊บบ แต่ไม่นาน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;playwright&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.เสร็จจากข้างบนก็มาสร้างไฟล์สำหรับเขียน Bot กัน, ได้ไฟล์แล้วก็เปิดด้วย IDE ที่ตัวเองถนัดได้เลยครับ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;touch&lt;/span&gt; &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5.ต่อด้วย Import Playwright แล้วก็สร้าง async ฟังชั่นก์เปล่าๆ ไว้รอลงรายละเอียด ตรงนี้ตัว Browser ผมจะใช้เป็นตัว Chromium นะครับ ถ้าอยากใช้อย่างอื่นก็ได้เหมือนกัน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;playwright&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// Coding here&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6.รัน Browser, สร้าง Context แล้วก็ Page&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1140&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตอนที่เรารัน Browser เราสามารถ run แบบ headless ได้ คือแบบไม่ได้แสดง UI ให้เราเห็น แต่กรณีนี้เผื่อเราอยากลุ้น Bot เราไปด้วย เราสามารถ set headless mode = false ได้ พอเราสร้าง browser เสร็จเราต่อด้วยการสร้าง context เอาไว้เก็บ page ของเราต่อ ซึ่ง 1 context ก็สามารถสร้างได้หลาย page เลย แต่ในตัวอย่างนี้เราสร้างหน้าเดียวพอครับ&lt;/p&gt;

&lt;p&gt;7.มาแกะ Elements กัน &lt;br&gt;
ตรงนี้จะสำคัญหน่อย เพราะจะมีเทคนิคของการทำ Web Scraping เข้ามาเสริม คือเราต้องหา "ที่อยู่" ของปุ่มหรือกล่องข้อความที่จะให้ Bot ทำในสิ่งที่เราต้องทำแทนเรา เช่นการ Click หรือ Typing อะไรลงไป &lt;/p&gt;

&lt;p&gt;Playwright จะสามารถหา element หรือ node พวกนั้นได้ผ่านทาง Selector engine เช่น CSS selectors, XPath, Full XPath selectors, HTML Attributes ต่างๆ เช่นพวก id, class, text, placeholder and etc. พร้อมทั้งยังมีความสามารถ Auto-wait ที่ช่วยให้รอ element นั้นปรากฎขึ้นมาก่อน ถึงจะเรียกคำสั่งที่กระทำกับ element นั้นให้.&lt;br&gt;
เราสามารถหา element ที่เราต้องการผ่านทาง Developer tool -&amp;gt; Inspect Element ของ Browser ที่เราใช้ โดยการเปิดจาก&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftze1tv5dw0oa9norguo0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftze1tv5dw0oa9norguo0.png" alt="Alt Text" width="700" height="353"&gt;&lt;/a&gt;&lt;br&gt;
จากรูปด้านล่าง สมมติว่าเราหา Element ที่เราต้องการจนเจอแล้ว เราสามารถใช้ตัวช่วย ที่จะหา path ของ element หรือ node ที่เราต้องการ &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4q9hu8d6v2tx3jliqor0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4q9hu8d6v2tx3jliqor0.png" alt="Alt Text" width="800" height="457"&gt;&lt;/a&gt;&lt;br&gt;
พอเราเจอปุ่มหรือกล่องข้อความที่ต้องการ เราก็ทำการ Copy path ที่เราได้จากข้างบน มาเก็บไว้ในโค้ดเราได้เลยครับ (ตัวอย่างจะเก็บในแบบของ Full XPath)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Login elements full XPath&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginToSystemButtonPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[1]/div/header/div[1]/section/ul/li[1]/button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginEmailBoxPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[2]/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div[2]/form/div[2]/input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginPasswordBoxPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[2]/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div[2]/form/div[3]/input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginSubmitButtonPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[2]/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div[2]/form/div[6]/input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Submit to buy element&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submitToBuyButtonPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[1]/div/div[3]/div[2]/div/section[1]/div[2]/aside/div/div[2]/div/button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หรือเราจะทำท่านี้ก็ได้ เช่น อยากให้ Click element ที่มี Text ที่เราต้องการ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shoeSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;44&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=EU &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;shoeSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตัวอย่างข้างบนก็จะเป็น "รอ" แล้ว Click ที่ element นั้นทันที ถ้าเจอ Text ที่มีคำว่า EU 44&lt;/p&gt;

&lt;p&gt;8.ประกอบร่าง&lt;br&gt;
เมื่อเราได้เหล่า elements ที่เราต้องการครบเรียบร้อยแล้ว เราก็มาเรียง action ตามแพลนที่เราวางไว้ จะเห็นว่าฟังก์ชั่นส่วนใหญ่ ก็จะใช้อย่างตรงไปตรงมา ส่วนตัวผมคิดว่าอ่านง่ายพอสมควรครับ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;selectors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;playwright&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1140&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;itemLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Let you guess :P&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Go to an item and login&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itemLink&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Login elements&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginToSystemButtonPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[1]/div/header/div[1]/section/ul/li[1]/button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginEmailBoxPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[2]/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div[2]/form/div[2]/input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginPasswordBoxPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[2]/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div[2]/form/div[3]/input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loginSubmitButtonPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[2]/div/div/div/div/div/div/div/div/div/div/div/div/div/div/div[2]/form/div[6]/input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Login into the system action&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginToSystemButtonPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginEmailBoxPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginPasswordBoxPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginSubmitButtonPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Wait and select shoe size&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shoeSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;44&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=EU &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;shoeSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Submit to buy element&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submitToBuyButtonPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;//html/body/div[2]/div/div/div[1]/div/div[3]/div[2]/div/section[1]/div[2]/aside/div/div[2]/div/button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;submitToBuyButtonPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Do the next steps&lt;/span&gt;
    &lt;span class="cm"&gt;/*
    6. Wait for the Payment page (Checkout page)
    7. Input CVV &amp;amp; Credit card detail
    8. Click Continue button
    9. Click Checkout button
    10. Which me luck
    */&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TESTING 💊
&lt;/h2&gt;

&lt;p&gt;จาก Code ด้านบนเราก็มาลองรันดูได้เลยครับ ด้วยคำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;พอรันแล้วก็จะพบกับหน้าที่ว่างเปล่า พร้อม error log ผ่ามๆๆ&lt;br&gt;
เพราะเราไม่มี itemLink ของสินค้าจริงๆมาแปะให้ลองครับ&lt;/p&gt;

&lt;h2&gt;
  
  
  SUMMARY 🔮
&lt;/h2&gt;

&lt;p&gt;สุดท้ายแล้ว มันเป็นแค่การทำอะไรสนุกๆ เพราะความขี้เกียจ เลยแค่อยากลองทำดู พร้อมทั้งเป็นไกด์ให้กับคนที่สนใจ อยากลองทำ Automation หรือ Testing อะไรสักอย่างกับเว็บของตัวเองดู เพราะการทำพวก Bot หรือ Web Scraping แนวนี้ ผมรู้สึกว่ามันไม่ค่อยขาวสะอาดมากเท่าไหร่ครับ มันเลยมีทั้งเทคนิค, ความยากและซับซ้อนกว่าที่ผมเล่าไว้ข้างบนเยอะเลย&lt;/p&gt;

&lt;p&gt;ส่วนสำหรับคนที่สนใจการทำ Web Automation กับ Playwright หรือ Web Scraping ก็ลองเข้าไปอ่านได้ที่ลิ้งที่ผมแปะไว้ให้ด้านล่างนี้ได้เลยครับ&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/playwright" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Web_scraping" rel="noopener noreferrer"&gt;Web Scraping&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devhints.io/xpath" rel="noopener noreferrer"&gt;Xpath&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ก่อนจากกัน...ฝาก page สนุกๆไว้ให้ติดตามผ่านทาง Facebook กันอีกทางครับ&lt;br&gt;
&lt;a href="https://www.facebook.com/igroomgrimonthefloor/" rel="noopener noreferrer"&gt;https://www.facebook.com/igroomgrimonthefloor/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;อยากให้ทุกคนสนุกกับการเขียนโค้ดครับ&lt;br&gt;
Be lazy &amp;amp; Happy Coding 🤤🖥🤗&lt;/p&gt;

</description>
      <category>webscraping</category>
      <category>playwright</category>
      <category>puppeteer</category>
      <category>node</category>
    </item>
  </channel>
</rss>
