इस ट्यूटोरियल में, आप सीखेंगे कि आप लिंक पर क्लिक करने, फॉर्म भरने और फाइल अपलोड करने के लिए मैकेनाइज का उपयोग कैसे कर सकते हैं। आप यह भी सीखेंगे कि आप पेज ऑब्जेक्ट्स को मैकेनाइज कैसे कर सकते हैं और Google खोज को स्वचालित कैसे करें और इसके परिणामों को कैसे सहेज सकते हैं।
विषय
- एकल पृष्ठ बनाम पृष्ठ पर अंक लगाना
- मशीनीकरण
- एजेंट
- पेज
- नोकोगिरी तरीके
- लिंक
- क्लिक करें
- फ़ॉर्म
एकल पेज बनाम पेजिनेशन
अब तक हमने यह पता लगाने में कुछ समय बिताया है कि हम नोकोगिरी का उपयोग करके एक पृष्ठ की स्क्रीन को कैसे स्क्रैप कर सकते हैं। यह एक कदम आगे बढ़ने और एकाधिक पृष्ठों से सामग्री निकालने का तरीका सीखने का एक अच्छा आधार था।
आखिरकार, हम जिस समस्या को हल करने का प्रयास कर रहे हैं, उसमें 140 से अधिक एपिसोड से सामग्री प्राप्त करना शामिल है - जो कि किसी एक वेब पेज में उचित रूप से फिट होने की तुलना में अधिक सामग्री है। हमें पेजिनेशन के साथ काम करना है और यह पता लगाने की जरूरत है कि खरगोश के छेद के नीचे सामग्री का पालन कैसे किया जाए।
यह वह जगह है जहां नोकोगिरी रुकती है और मैकेनाइज नामक एक अन्य उपयोगी रत्न चलन में आता है।
मशीनीकरण
मशीनीकरण एक और शक्तिशाली उपकरण है जिसमें पेशकश करने के लिए बहुत सारे उपहार हैं। यह अनिवार्य रूप से आपको उन वेबसाइटों के साथ बातचीत को स्वचालित करने में सक्षम बनाता है जिनसे आपको सामग्री निकालने की आवश्यकता होती है। उस अर्थ में यह मुझे कुछ कार्यक्षमता की याद दिलाता है जिसे आप Capybara के साथ परीक्षण से जान सकते हैं।
मुझे गलत मत समझो, एक ही पृष्ठ पर नोकोगिरी के साथ खेलना अपने आप में बहुत बढ़िया है, लेकिन अधिक मसालेदार डेटा निष्कर्षण नौकरियों के लिए, हमें थोड़ी अधिक अश्वशक्ति की आवश्यकता है। हम अनिवार्य रूप से जितने चाहें उतने पृष्ठों के माध्यम से क्रॉल कर सकते हैं और उनके तत्वों के साथ बातचीत कर सकते हैं-मानव व्यवहार का अनुकरण और स्वचालित कर सकते हैं। बहुत शक्तिशाली सामान!
यह रत्न आपको लिंक का अनुसरण करने, फ़ॉर्म फ़ील्ड भरने और उस डेटा को सबमिट करने में सक्षम बनाता है—यहां तक कि कुकीज़ से निपटना भी टेबल पर है। इसका मतलब है कि आप निजी सत्रों में उपयोगकर्ताओं के लॉगिन का अनुकरण भी कर सकते हैं और केवल उस साइट से सामग्री प्राप्त कर सकते हैं जिस पर आपकी पहुंच है।
आप अपने क्रेडेंशियल के साथ लॉगिन भरें और मैकेनाइज को बताएं कि कैसे आगे बढ़ना है। चूंकि आप लिंक पर क्लिक कर सकते हैं और फॉर्म जमा कर सकते हैं, इसलिए ऐसा बहुत कम है जो आप इस टूल से नहीं कर सकते। इसका नोकोगिरी से घनिष्ठ संबंध है और यह इस पर निर्भर भी करता है। हारून पैटरसन फिर से इस प्यारे रत्न के लेखकों में से एक है।
मैकेनाइज एजेंट को इंस्टेंट करना
इससे पहले कि हम चीजों का मशीनीकरण शुरू कर सकें, हमें एक मैकेनाइज एजेंट को इंस्टेंट करना होगा।
some_scraper.rb
require 'mechanize' agent = Mechanize.new
यह agent
एक पेज लाने के लिए इस्तेमाल किया जाएगा, जैसा कि हमने नोकोगिरी के साथ किया था।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url)
यहां क्या होता है कि मैकेनाइज एजेंट को पॉडकास्ट पेज और उसकी कुकीज मिल जाती हैं।
पृष्ठ सामग्री निकालना
अब हमारे पास एक पृष्ठ है जो निष्कर्षण के लिए तैयार है। ऐसा करने से पहले, मैं अनुशंसा करता हूं कि हम inspect
. का उपयोग करके हुड के नीचे एक नज़र डालें विधि।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) puts page.inspect
आउटपुट काफी वास्तविक है। एक नज़र डालें और खुद देखें कि Mechanize::Page
. क्या है वस्तु से मिलकर बनता है। यहां आप उस पेज की सभी विशेषताएँ देख सकते हैं।
मेरे लिए, जिस डेटा को आप निकालना चाहते हैं, उसे काटने के लिए यह वास्तव में एक आसान वस्तु है।
आउटपुट
#<Mechanize::Page {url #https://betweenscreens.fm/>} {meta_refresh} {title "Between | Screens "} {iframes #<Mechanize::Page::Frame nil "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/290328784&color=ff0000&auto...> #<Mechanize::Page::Frame nil "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/290126141&color=ff0000&auto...> #<Mechanize::Page::Frame nil "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/289018386&color=ff0000&auto...> #<Mechanize::Page::Frame nil "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/287425105&color=ff0000&auto...> #<Mechanize::Page::Frame nil "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/287105342&color=ff0000&auto...> #<Mechanize::Page::Frame nil "https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/221003494&color=ff0000&auto...> #<Mechanize::Page::Frame nil "">https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/218101809&color=ff0000&auto...} {frames} {links #<Mechanize::Page::Link "Logo cube" "/"> #https://github.com/vis-kid/betweenscreens"> #<Mechanize::Page::Link "about" "pages/about/"> #<Mechanize::Page::Link "design" "design/"> #<Mechanize::Page::Link "code" "code/"> #<Mechanize::Page::Link "Randy J. Hunt" "episodes/144/"> #<Mechanize::Page::Link "Jason Long" "episodes/143/"> #<Mechanize::Page::Link "David Heinemeier Hansson" "episodes/142/"> #<Mechanize::Page::Link "Zach Holman" "episodes/141/"> #<Mechanize::Page::Link "Joel Glovier" "episodes/140/"> #<Mechanize::Page::Link "João Ferreira" "episodes/139/"> #<Mechanize::Page::Link "Corwin Harrell" "episodes/138/"> #<Mechanize::Page::Link "Older Stuff »" "page/2/"> #<Mechanize::Page::Link "Exercise" "/tags/exercise/"> #<Mechanize::Page::Link "Company benefits" "/tags/company-benefits/"> #<Mechanize::Page::Link "Tmux" "/tags/tmux/"> #<Mechanize::Page::Link "FileTask" "/tags/filetask/"> #<Mechanize::Page::Link "Decision making" "/tags/decision-making/"> #<Mechanize::Page::Link "Favorite feature" "/tags/favorite-feature/"> #<Mechanize::Page::Link "Working out" "/tags/working-out/"> #<Mechanize::Page::Link "Scott Savarie" "/tags/scott-savarie/"> #<Mechanize::Page::Link "Titles" "/tags/titles/"> #<Mechanize::Page::Link "Erik Spiekermann" "/tags/erik-spiekermann/"> #<Mechanize::Page::Link "Newbie mistakes" "/tags/newbie-mistakes/"> #<Mechanize::Page::Link "Playbook" "/tags/playbook/"> #<Mechanize::Page::Link "Delegation" "/tags/delegation/"> #<Mechanize::Page::Link "Heat maps" "/tags/heat-maps/"> #<Mechanize::Page::Link "Europe" "/tags/europe/"> #<Mechanize::Page::Link "Sizing type" "/tags/sizing-type/"> #<Mechanize::Page::Link "Focus" "/tags/focus/"> #<Mechanize::Page::Link "Virtual assistants" "/tags/virtual-assistants/"> #<Mechanize::Page::Link "Writing" "/tags/writing/"> #<Mechanize::Page::Link "Hacking" "/tags/hacking/"> #<Mechanize::Page::Link "Joel Glovier" "/tags/joel-glovier/"> #<Mechanize::Page::Link "Corwin Harrell" "/tags/corwin-harrell/"> #<Mechanize::Page::Link "Mario C. Delgado" "/tags/mario-c-delgado/"> #<Mechanize::Page::Link "Tom Dale" "/tags/tom-dale/"> #<Mechanize::Page::Link "Obie Fernandez" "/tags/obie-fernandez/"> #<Mechanize::Page::Link "Chad Pytel" "/tags/chad-pytel/"> #<Mechanize::Page::Link "Zach Holman" "/tags/zach-holman/"> #<Mechanize::Page::Link "Max Luster" "/tags/max-luster/"> #<Mechanize::Page::Link "Kyle Fiedler" "/tags/kyle-fiedler/"> #<Mechanize::Page::Link "Roberto Machado" "/tags/roberto-machado/">} {forms}>
यदि आप स्वयं HTML पृष्ठ पर एक नज़र डालना चाहते हैं, तो आप body
. पर टैग कर सकते हैं या content
तरीके।
some_scraper.rb
... print page.body ...
आउटपुट
<!doctype html> <html> <head> <meta charset="utf-8" /> <meta http-equiv='X-UA-Compatible' content='IE=edge;chrome=1' /> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <meta name="viewport" content="initial-scale=1"> <title>Between | Screens </title> <link rel="alternate" type="application/atom+xml" title="Atom Feed" href="/feed.xml" /> <link href="stylesheets/all-11b45acc.css" rel="stylesheet" /> <script src="javascripts/all-4c20da82.js"></script> </head> <body> <header> <div id="logo"> <a href="/"><img src="images/Between_Screens_Logo_Cube_Up-539d6997.svg" alt="Logo cube" /></a> </div> <nav class="navigation"> <ul class="nav-list"> fork">https://github.com/vis-kid/betweenscreens">fork! <li><a href="pages/about/">about</a></li> <li><a href="design/">design</a></li> <li><a href="code/">code</a></li> </ul> </nav> </header> <div id="main" role="main"> <div class='posts'> <ul> <li> <article class="index-article"> <span class='post-date'>Oct 27 | 2016</span><h2 class='post-title'><a href="episodes/144/">Randy J. Hunt</a></h2> <h3 class='topic-list'>Organizing teams | Diversity | Desires | Pizza rule | Effective over clever | Novel solutions | Straightforwardness | Research | Coffeeshop test | Small changes | Reducing errors | Granular diffs</h3> <div class='soundcloud-player-small'> <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/290328784&color=ff0000&...> </div> </article> </li> <li> <article class="index-article"> <span class='post-date'>Oct 25 | 2016</span><h2 class='post-title'><a href="episodes/143/">Jason Long</a></h2> <h3 class='topic-list'>Open source | Empathy | Lower barriers | Learning tool | Design contributions | Git website | Branding | GitHub | Neovim | Tmux | Design love | Knowing audiences | Showing work | Dribbble | Progressions | Ideas</h3> <div class='soundcloud-player-small'> <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/290126141&color=ff0000&...> </div> </article> </li> <li> <article class="index-article"> <span class='post-date'>Oct 18 | 2016</span><h2 class='post-title'><a href="episodes/142/">David Heinemeier Hansson</a></h2> <h3 class='topic-list'>Rails community | Tone | Technical disagreements | Community policing | Ungratefulness | No assholes allowed | Basecamp | Open source persona | Aspirations | Guarding motivations | Dealing with audiences | Pressure | Honesty | Diverse opinions | Small talk</h3> <div class='soundcloud-player-small'> <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/289018386&color=ff0000&...> </div> </article> </li> <li> <article class="index-article"> <span class='post-date'>Oct 12 | 2016</span><h2 class='post-title'><a href="episodes/141/">Zach Holman</a></h2> <h3 class='topic-list'>Getting Fired | Taboo | Transparency | Different Perspectives | Timing | Growth Stages | Employment & Dating | Managers | At-will Employment | Tech Industry | Europe | Low hanging Fruits | Performance Improvement Plans | Meeting Goals | Surprise Firings | Firing Fast | Mistakes | Company Culture | Communication</h3> <div class='soundcloud-player-small'> <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/287425105&color=ff0000&...> </div> </article> </li> <li> <article class="index-article"> <span class='post-date'>Oct 10 | 2016</span><h2 class='post-title'><a href="episodes/140/">Joel Glovier</a></h2> <h3 class='topic-list'>Digital Product Design | Product Design @ GitHub | Loving Design | Order & Chaos | Drawing | Web Design | HospitalRun | Diversity | Startup Culture | Improving Lives | CURE International | Ember | Offline First | Hospital Information System | Designers & Open Source</h3> <div class='soundcloud-player-small'> <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/287105342&color=ff0000&...> </div> </article> </li> <li> <article class="index-article"> <span class='post-date'>Aug 26 | 2015</span><h2 class='post-title'><a href="episodes/139/">João Ferreira</a></h2> <h3 class='topic-list'>Masters @ Work | Subvisual | Deadlines | Design personality | Design problems | Team | Pushing envelopes | Delightful experiences | Perfecting details | Company values</h3> <div class='soundcloud-player-small'> <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/221003494&color=ff0000&...> </div> </article> </li> <li> <article class="index-article"> <span class='post-date'>Aug 06 | 2015</span><h2 class='post-title'><a href="episodes/138/">Corwin Harrell</a></h2> <h3 class='topic-list'>Q&A | 01 | University | Graphic design | Design setup | Sublime | Atom | thoughtbot | Working location | Collaboration & pairing | Vim advocates | Daily routine | Standups | Clients | Coffee walks | Investment Fridays |</h3> <div class='soundcloud-player-small'> <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/218101809&color=ff0000&...> </div> </article> </li> </ul> </div> <section> <div class='pagination-link'><a href="page/2/">Older Stuff »</a></div> </section> </div> <footer> <div class='footer-tags'> <h3>Random Tags</h3> <ul class='random-tag-list'> <li><a href="/tags/exercise/">Exercise</a></li> <li><a href="/tags/company-benefits/">Company benefits</a></li> <li><a href="/tags/tmux/">Tmux</a></li> <li><a href="/tags/filetask/">FileTask</a></li> <li><a href="/tags/decision-making/">Decision making</a></li> <li><a href="/tags/favorite-feature/">Favorite feature</a></li> <li><a href="/tags/working-out/">Working out</a></li> <li><a href="/tags/scott-savarie/">Scott Savarie</a></li> <li><a href="/tags/titles/">Titles</a></li> <li><a href="/tags/erik-spiekermann/">Erik Spiekermann</a></li> <li><a href="/tags/newbie-mistakes/">Newbie mistakes</a></li> <li><a href="/tags/playbook/">Playbook</a></li> <li><a href="/tags/delegation/">Delegation</a></li> <li><a href="/tags/heat-maps/">Heat maps</a></li> <li><a href="/tags/europe/">Europe</a></li> <li><a href="/tags/sizing-type/">Sizing type</a></li> <li><a href="/tags/focus/">Focus</a></li> <li><a href="/tags/virtual-assistants/">Virtual assistants</a></li> <li><a href="/tags/writing/">Writing</a></li> <li><a href="/tags/hacking/">Hacking</a></li> </ul> </div> <div class='recent-posts'> <h3>Random Interviewees</h3> <ul> <li><a href="/tags/joel-glovier/">Joel Glovier</a></li> <li><a href="/tags/corwin-harrell/">Corwin Harrell</a></li> <li><a href="/tags/mario-c-delgado/">Mario C. Delgado</a></li> <li><a href="/tags/tom-dale/">Tom Dale</a></li> <li><a href="/tags/obie-fernandez/">Obie Fernandez</a></li> <li><a href="/tags/chad-pytel/">Chad Pytel</a></li> <li><a href="/tags/zach-holman/">Zach Holman</a></li> <li><a href="/tags/max-luster/">Max Luster</a></li> <li><a href="/tags/kyle-fiedler/">Kyle Fiedler</a></li> <li><a href="/tags/roberto-machado/">Roberto Machado</a></li> </ul> </div> </footer> </body> </html>
चूँकि इस पॉडकास्ट में पेज पर बहुत कम संख्या में विभिन्न तत्व हैं, यहाँ Mechanize::Page
है जो github.com से वापस आ जाता है। इसमें देखने के लिए सामग्री की एक बड़ी विविधता है। मुझे लगता है कि इसे महसूस करने के लिए यह महत्वपूर्ण है।
आउटपुट github.com
#<Mechanize::Page {url #https://github.com/>} {meta_refresh} {title "How people build software · GitHub"} {iframes} {frames} {links #<Mechanize::Page::Link "Skip to content" "#start-of-content"> #https://github.com/"> #<Mechanize::Page::Link "\n Personal\n" "/personal"> #<Mechanize::Page::Link "\n Open source\n" "/open-source"> #<Mechanize::Page::Link "\n Business\n" "/business"> #<Mechanize::Page::Link "\n Explore\n" "/explore"> #<Mechanize::Page::Link "Sign up" "/join?source=header-home"> #<Mechanize::Page::Link "Sign in" "/login"> #<Mechanize::Page::Link "Pricing" "/pricing"> #<Mechanize::Page::Link "Blog" "/blog"> #https://help.github.com"> #https://github.com/search"> #https://help.github.com/terms"> #https://help.github.com/privacy"> #<Mechanize::Page::Link "Sign up for GitHub" "/join?source=button-home"> #<Mechanize::Page::Link "\n \n \n \n \n A whole new Universe\n \n Learn about the exciting features and announcements revealed at this year's GitHub Universe conference.\n \n \n " "/universe-2016"> #<Mechanize::Page::Link "Individuals " "/personal"> #<Mechanize::Page::Link "Communities " "/open-source"> #<Mechanize::Page::Link "Businesses " "/business"> #<Mechanize::Page::Link "NASA" "//github.com/nasa"> #<Mechanize::Page::Link "Sign up for GitHub" "/join?source=button-home"> #https://github.com/contact"> #https://developer.github.com"> #https://training.github.com"> #https://shop.github.com"> #https://github.com/blog"> #https://github.com/about"> #https://github.com"> #https://github.com/site/terms"> #https://github.com/site/privacy"> #https://github.com/security"> #https://status.github.com/"> #https://help.github.com"> #<Mechanize::Page::Link "Reload" ""> #<Mechanize::Page::Link "Reload" "">} {forms #<Mechanize::Form {name nil} {method "GET"} {action "/search"} {fields [hidden:0x3feb90f8297c type: hidden name: utf8 value: ✓] [text:0x3feb90f827d8 type: text name: q value: ]} {radiobuttons} {checkboxes} {file_uploads} {buttons}> #<Mechanize::Form {name nil} {method "POST"} {action "/join"} {fields [hidden:0x3feb90f7be38 type: hidden name: utf8 value: ✓] [hidden:0x3feb90f7bbb8 type: hidden name: authenticity_token value: vjRATKj7smXreq6Lt02r+MzW+ewWoi+fRzQXPedFAlOZgwzxQ0dZnChirhDfd7vyWZZZBO+ZFydLNedjIEDsrQ==] [text:0x3feb90f7b9d8 type: text name: user[login] value: ] [text:0x3feb90f7b7f8 type: text name: user[email] value: ] [field:0x3feb90f7b654 type: password name: user[password] value: ] [hidden:0x3feb90f7b474 type: hidden name: source value: form-home]} {radiobuttons} {checkboxes} {file_uploads} {buttons [button:0x3feb90f7a038 type: submit name: value: ]}>}>
पॉडकास्ट पर वापस, आप एन्कोडिंग, HTTP प्रतिक्रिया कोड, यूआरआई, या प्रतिक्रिया शीर्षलेख जैसी चीज़ों को भी देख सकते हैं।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) puts 'Encodings' puts page.encodings puts 'Repsonse Headers' puts page.response puts 'HTTP response code' puts page.code puts 'URI' puts page.uri
आउटपुट
Encodings EUC-JP utf-8 utf-8 Repsonse Headers {"server"=>"GitHub.com", "date"=>"Sat, 29 Oct 2016 17:56:00 GMT", "content-type"=>"text/html; charset=utf-8", "transfer-encoding"=>"chunked", "last-modified"=>"Fri, 28 Oct 2016 01:48:56 GMT", "access-control-allow-origin"=>"*", "expires"=>"Sat, 29 Oct 2016 18:06:00 GMT", "cache-control"=>"max-age=600", "content-encoding"=>"gzip", "x-github-request-id"=>"501C936D:C723:1631523C:5814E2B0"} HTTP response code 200 URI https://betweenscreens.fm/
यदि आप गहराई में जाना चाहते हैं तो और भी बहुत कुछ है। मैं इसे उस पर छोड़ दूँगा।
नोकोगिरी तरीके
at
search
पेजों से डेटा को परिमार्जन करने के लिए मशीनीकरण नोकोगिरी का उपयोग करता है। आप पहले लेख में नोकोगिरी के बारे में जो कुछ भी सीखा है उसे लागू कर सकते हैं और इसे मैकेनाइज पेजों पर भी इस्तेमाल कर सकते हैं। इसका मतलब है कि आप आम तौर पर अपनी स्क्रैपिंग जरूरतों के लिए पेजों और नोकोगिरी विधियों को नेविगेट करने के लिए मैकेनाइज का उपयोग करते हैं।
उदाहरण के लिए, यदि आप किसी एक वस्तु को खोजना चाहते हैं, तो आप at
. का उपयोग कर सकते हैं , जबकि search
सभी ऑब्जेक्ट लौटाता है जो किसी विशेष पृष्ठ पर चयनकर्ता से मेल खाएगा। इसे फिर से लिखने के लिए, ये विधियां नोकोगिरी दस्तावेज़ ऑब्जेक्ट्स और मैकेनाइज पेज ऑब्जेक्ट्स दोनों पर काम करेंगी।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) first_title = page.at('h2.post-title') all_titles = page.search('h2.post-title') all_titles.each do |title| puts title end puts " * "*33 puts first_title
आउटपुट
<h2 class="post-title"><a href="episodes/144/">Randy J. Hunt</a></h2> <h2 class="post-title"><a href="episodes/143/">Jason Long</a></h2> <h2 class="post-title"><a href="episodes/142/">David Heinemeier Hansson</a></h2> <h2 class="post-title"><a href="episodes/141/">Zach Holman</a></h2> <h2 class="post-title"><a href="episodes/140/">Joel Glovier</a></h2> <h2 class="post-title"><a href="episodes/139/">João Ferreira</a></h2> <h2 class="post-title"><a href="episodes/138/">Corwin Harrell</a></h2> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * <h2 class="post-title"><a href="episodes/144/">Randy J. Hunt</a></h2>
लिंक
links
link_with
links_with
हम अपनी पसंद के अनुसार पूरी साइट को नेविगेट भी कर सकते हैं। संभवत:मैकेनाइज का सबसे महत्वपूर्ण हिस्सा आपको लिंक के साथ खेलने देने की क्षमता है। अन्यथा आप अपने आप ही नोकोगिरी से काफी हद तक चिपके रह सकते हैं। आइए एक नज़र डालते हैं कि अगर हम किसी पेज से उसके लिंक के लिए पूछते हैं तो हमें क्या मिलता है।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) puts "#{page.links}"
आउटपुट
[#<Mechanize::Page::Link "Logo cube" "/"> , #https://github.com/vis-kid/betweenscreens"> , #<Mechanize::Page::Link "about" "pages/about/"> , #<Mechanize::Page::Link "design" "design/"> , #<Mechanize::Page::Link "code" "code/"> , #<Mechanize::Page::Link "Randy J. Hunt" "episodes/144/"> , #<Mechanize::Page::Link "Jason Long" "episodes/143/"> , #<Mechanize::Page::Link "David Heinemeier Hansson" "episodes/142/"> , #<Mechanize::Page::Link "Zach Holman" "episodes/141/"> , #<Mechanize::Page::Link "Joel Glovier" "episodes/140/"> , #<Mechanize::Page::Link "João Ferreira" "episodes/139/"> , #<Mechanize::Page::Link "Corwin Harrell" "episodes/138/"> , #<Mechanize::Page::Link "Older Stuff »" "page/2/"> , #<Mechanize::Page::Link "Exercise" "/tags/exercise/"> , #<Mechanize::Page::Link "Company benefits" "/tags/company-benefits/"> , #<Mechanize::Page::Link "Tmux" "/tags/tmux/"> , #<Mechanize::Page::Link "FileTask" "/tags/filetask/"> , #<Mechanize::Page::Link "Decision making" "/tags/decision-making/"> , #<Mechanize::Page::Link "Favorite feature" "/tags/favorite-feature/"> , #<Mechanize::Page::Link "Working out" "/tags/working-out/"> , #<Mechanize::Page::Link "Scott Savarie" "/tags/scott-savarie/"> , #<Mechanize::Page::Link "Titles" "/tags/titles/"> , #<Mechanize::Page::Link "Erik Spiekermann" "/tags/erik-spiekermann/"> , #<Mechanize::Page::Link "Newbie mistakes" "/tags/newbie-mistakes/"> , #<Mechanize::Page::Link "Playbook" "/tags/playbook/"> , #<Mechanize::Page::Link "Delegation" "/tags/delegation/"> , #<Mechanize::Page::Link "Heat maps" "/tags/heat-maps/"> , #<Mechanize::Page::Link "Europe" "/tags/europe/"> , #<Mechanize::Page::Link "Sizing type" "/tags/sizing-type/"> , #<Mechanize::Page::Link "Focus" "/tags/focus/"> , #<Mechanize::Page::Link "Virtual assistants" "/tags/virtual-assistants/"> , #<Mechanize::Page::Link "Writing" "/tags/writing/"> , #<Mechanize::Page::Link "Hacking" "/tags/hacking/"> , #<Mechanize::Page::Link "Joel Glovier" "/tags/joel-glovier/"> , #<Mechanize::Page::Link "Corwin Harrell" "/tags/corwin-harrell/"> , #<Mechanize::Page::Link "Mario C. Delgado" "/tags/mario-c-delgado/"> , #<Mechanize::Page::Link "Tom Dale" "/tags/tom-dale/"> , #<Mechanize::Page::Link "Obie Fernandez" "/tags/obie-fernandez/"> , #<Mechanize::Page::Link "Chad Pytel" "/tags/chad-pytel/"> , #<Mechanize::Page::Link "Zach Holman" "/tags/zach-holman/"> , #<Mechanize::Page::Link "Max Luster" "/tags/max-luster/"> , #<Mechanize::Page::Link "Kyle Fiedler" "/tags/kyle-fiedler/"> , #<Mechanize::Page::Link "Roberto Machado" "/tags/roberto-machado/"> ]
पवित्र मोली, आइए इसे तोड़ दें। चूंकि हमने मैकेनाइज को कहीं और देखने के लिए नहीं कहा है, हमें केवल उसी पहले पृष्ठ से लिंक की एक सरणी मिली है। मशीनीकरण उस पृष्ठ से अवरोही क्रम में जाता है और आपको ऊपर से नीचे तक लिंक की यह सूची देता है। मैंने हरे रंग के पॉइंटर्स के साथ विभिन्न लिंक्स के साथ एक छोटी सी छवि बनाई है जिसे आप आउटपुट में देख सकते हैं।
वैसे, यह आपको मेरे पॉडकास्ट के रीडिज़ाइन का अंतिम परिणाम पहले से ही दिखा रहा है। मुझे लगता है कि यह संस्करण प्रदर्शन उद्देश्यों के लिए थोड़ा बेहतर है। आपको यह भी पता चलता है कि अंतिम परिणाम कैसा दिखता है और मुझे अपनी पुरानी सिनात्रा साइट को स्क्रैप करने की आवश्यकता क्यों पड़ी।
स्क्रीनशॉट
हमेशा की तरह, हम उसमें से सिर्फ टेक्स्ट भी निकाल सकते हैं।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) page.links.each do |link| puts link.text end
आउटपुट
Logo cube fork! about design code Randy J. Hunt Jason Long David Heinemeier Hansson Zach Holman Joel Glovier João Ferreira Corwin Harrell Older Stuff » Exercise Company benefits Tmux FileTask Decision making Favorite feature Working out Scott Savarie Titles Erik Spiekermann Newbie mistakes Playbook Delegation Heat maps Europe Sizing type Focus Virtual assistants Writing Hacking Joel Glovier Corwin Harrell Mario C. Delgado Tom Dale Obie Fernandez Chad Pytel Zach Holman Max Luster Kyle Fiedler Roberto Machado
इन सभी लिंक को बल्क में प्राप्त करना बहुत उपयोगी या केवल थकाऊ हो सकता है। हमारे लिए सौभाग्य की बात है कि हमें जो चाहिए उसे ठीक करने के लिए हमारे पास कुछ उपकरण हैं।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) focus_link = agent.page.links.find { |link| link.text == 'Focus' } puts focus_link
आउटपुट
Focus
बूम! अब हम कहीं पहुँच रहे हैं! हम उस तरह के विशिष्ट लिंक पर ज़ूम इन कर सकते हैं। हम उन लिंक्स को लक्षित कर सकते हैं जो एक निश्चित मानदंड से मेल खाते हैं—जैसे इसका टेक्स्ट, उदाहरण के लिए—links_with
जैसे अच्छे एपीआई के साथ। या link_with
. साथ ही, यदि हमारे पास एकाधिक Focus
हैं लिंक, हम कोष्ठकों का उपयोग करके पृष्ठ पर किसी विशेष संख्या पर ज़ूम इन कर सकते हैं []
।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) focus_link = agent.page.links_with(:text => 'Focus')[2] puts focus_link
यदि आप लिंक टेक्स्ट के बाद नहीं बल्कि लिंक के पीछे हैं, तो आपको केवल एक विशेष href
निर्दिष्ट करने की आवश्यकता है उस लिंक को खोजने के लिए। मशीनीकरण आपके रास्ते में नहीं आएगा। text
. के बजाय , आप href
. के साथ विधियों को फीड करते हैं .
some_scraper.rb
page = agent.page.link_with(href: '/episodes/95/') page = agent.page.links_with(href: '/episodes/95/')
यदि आप केवल वांछित टेक्स्ट के साथ पहला लिंक ढूंढना चाहते हैं, तो आप इस सिंटैक्स का भी उपयोग कर सकते हैं। बहुत सुविधाजनक और थोड़ा अधिक पठनीय।
some_scraper.rb
focus_links = agent.page.link_with(:text => 'Focus')
उस साथी का अनुसरण करने और इस Focus
के पीछे क्या छिपा है, यह देखने के बारे में क्या? संपर्क? आइए click
यह!
क्लिक करें
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) focus_links = agent.page.links.find { |link| link.text == 'Focus' }.click.links puts focus_links
इससे हमें पहले की तरह लिंक्स की एक और लंबी सूची मिल जाएगी। देखें कि .click.links
combine को संयोजित करना कितना आसान था . मशीनीकरण आपके लिए लिंक पर क्लिक करता है और नए गंतव्य के लिए पृष्ठ का अनुसरण करता है। चूंकि हमने लिंक की एक सूची का भी अनुरोध किया है, इसलिए हमें वे सभी लिंक मिलेंगे जो मैकेनाइज को उस नए पेज पर मिल सकते हैं।
मान लें कि मेरे पास एक ही साक्षात्कारकर्ता के दो टेक्स्ट लिंक हैं—एक जो टैग से लिंक करता है और एक हाल के एपिसोड से—और मैं इनमें से प्रत्येक पृष्ठ से लिंक प्राप्त करना चाहता हूं।
some_scraper.rb
require 'mechanize' agent = Mechanize.new podcast_url = "https://betweenscreens.fm/" page = agent.get(podcast_url) links = agent.page.links_with(text: "Some interviewee") links.each do |link| puts link.click.links end
यह आपको दोनों पृष्ठों के लिंक की एक सूची देगा। आप साक्षात्कारकर्ता के लिए प्रत्येक लिंक पर पुनरावृति करते हैं, और मैकेनाइज क्लिक किए गए लिंक का अनुसरण करता है और आपके लिए नए पेज पर मिलने वाले लिंक को एकत्र करता है। नीचे आपको कुछ उदाहरण मिल सकते हैं जहां आप आरंभ करने के लिए संयोजनों की तुलना कर सकते हैं।
some_scraper.rb
agent.page.links.find { |l| l.text == 'Focus' } agent.page.links.find { |l| l.text == 'Focus' }.click agent.page.link_with(text: 'Focus') agent.page.links_with(text: 'Focus')[0] agent.page.links_with(text: 'Focus')[1].click agent.page.links_with(text: 'Focus')[2].click.links agent.page.link_with(href: '/some-href') agent.page.link_with(href: '/some-href').click agent.page.links_with(href: '/some-href') agent.page.links_with(href: '/some-href').click
फ़ॉर्म
submit
field_with
checkbox_with
radiobuttons_with
file_uploads
आइए रूपों पर एक नजर डालते हैं!
some_scraper.rb
require 'mechanize' agent = Mechanize.new google_url = "https://google.com/" page = agent.get(google_url) forms = page.forms puts forms.inspect
आउटपुट
[#<Mechanize::Form # Attention!! {name "f"} # Attention!! {method "GET"} {action "/search"} {fields [hidden:0x3fea91d2eb08 type: hidden name: ie value: ISO-8859-1] [hidden:0x3fea91d2e964 type: hidden name: hl value: es] [hidden:0x3fea91d2e7e8 type: hidden name: source value: hp] [hidden:0x3fea91d2e5f4 type: hidden name: biw value: ] [hidden:0x3fea91d2e428 type: hidden name: bih value: ] # Attention!! [text:0x3fea91d2e248 type: name: q value: ] # Attention!! [hidden:0x3fea91d2bcb4 type: hidden name: gbv value: 1]} {radiobuttons} {checkboxes} {file_uploads} {buttons [submit:0x3fea91d2e0f4 type: submit name: btnG value: Buscar con Google] [submit:0x3fea91d2be80 type: submit name: btnI value: Voy a tener suerte]}> ]
Because we use the forms
method, we get an array returned—even when we only have one form returned to us. Now that we know that the form has the name "f"
, we can use the singular version form
to hone in on that one.
... {name "f"} ...
some_scraper.rb
require 'mechanize' agent = Mechanize.new google_url = "https://google.com/" page = agent.get(google_url) search_form = page.form('f') puts search_form.inspect
Using form('f')
, we singled out the particular form we want to work with. As a result, we will not get an array returned.
Output
#<Mechanize::Form # Attention!! {name "f"} # Attention!! {method "GET"} {action "/search"} {fields [hidden:0x3ffe9ce85ba4 type: hidden name: ie value: ISO-8859-1] [hidden:0x3ffe9ce859d8 type: hidden name: hl value: es] [hidden:0x3ffe9ce857bc type: hidden name: source value: hp] [hidden:0x3ffe9ce85618 type: hidden name: biw value: ] [hidden:0x3ffe9ce853e8 type: hidden name: bih value: ] # Attention!! [text:0x3ffe9ce851cc type: name: q value: ] # Attention!! [hidden:0x3ffe9ce84bdc type: hidden name: gbv value: 1]} {radiobuttons} {checkboxes} {file_uploads} {buttons [submit:0x3ffe9ce85078 type: submit name: btnG value: Buscar con Google] [submit:0x3ffe9ce84e48 type: submit name: btnI value: Voy a tener suerte]}>
We can also identify the name of the text input field (q
)।
... [text:0x3ffe9ce851cc type: name: q value: ] ...
We can target it by that name and set its value like Ruby attributes. All we need to do is provide it with a new value. You can see from the output example above that it is empty by default.
some_scraper.rb
require 'mechanize' agent = Mechanize.new google_url = "https://google.com/" page = agent.get(google_url) search_form = page.form('f') search_form.q = 'New Google Search' puts search_form.inspect
Output
#<Mechanize::Form {name "f"} {method "GET"} {action "/search"} {fields [hidden:0x3fcb85b6a784 type: hidden name: ie value: ISO-8859-1] [hidden:0x3fcb85b6a57c type: hidden name: hl value: es] [hidden:0x3fcb85b6a3b0 type: hidden name: source value: hp] [hidden:0x3fcb85b6a16c type: hidden name: biw value: ] [hidden:0x3fcb85b67f20 type: hidden name: bih value: ] # Attention!! [text:0x3fcb85b67d18 type: name: q value: New Google Search] # Attention!! [hidden:0x3fcb85b67728 type: hidden name: gbv value: 1]} {radiobuttons} {checkboxes} {file_uploads} {buttons [submit:0x3fcb85b67b9c type: submit name: btnG value: Buscar con Google] [submit:0x3fcb85b67994 type: submit name: btnI value: Voy a tener suerte]}>
As you can observe above, the value for the text field has changed to New Google Search
. Now we only need to submit
the form and collect the results from the page that Google returns. It couldn’t be any easier. Let’s search for something else this time!
some_scraper.rb
require 'mechanize' agent = Mechanize.new google_url = "https://google.com/" page = agent.get(google_url) search_form = page.form('f') search_form.q = 'GitHub TouchFart' page = agent.submit(search_form) pp page.search('h3.r').map(&:text)
Here I identified the search results header using a CSS selector h3.r
, mapped its text
, and pretty printed the results. Wasn’t that hard, was it? That is an easy example, sure, but think about the endless possibilities you have at your disposal with this!
Output
["GitHub - hungtruong/TouchFart: A fart app for the new Macbook ...", "TouchFart/TouchFart at master · hungtruong/TouchFart · GitHub", "Commits · hungtruong/TouchFart · GitHub", "Projects · hungtruong/TouchFart · GitHub", "Pull Requests · hungtruong/TouchFart · GitHub", "Issues · hungtruong/TouchFart · GitHub", "TouchFart/license.txt at master · hungtruong/TouchFart · GitHub", "Add autoplay attribute to <audio> tag and touchfart (er ... - GitHub", "Find file - File Finder · GitHub", "Fart app for the new Macbook Pro's Touch... #3860 on topic touchfart ..."]
Mechanize has different input fields available for you to play with. You can even upload files!
field_with
checkbox_with
radiobuttons_with
file_uploads
You can also identify radio buttons and checkboxes by their name and check them with—you guessed it—check
।
some_scraper.rb
form.radiobuttons_with(:name => 'gender')[3].check form.checkbox_with(:name => 'coder').check
Option tags offer users to select one item from a drop-down list. Again, we target them by name and select the option number we want.
some_scraper.rb
form.field_with(:name => 'countries').options[22].select
File uploads work similar to inputing text into forms by setting it like Ruby attributes. You identify the upload field and then specify the file path (file name) you want to transfer. It sounds more complicated than it is. Let’s have a look!
some_scraper.rb
form.file_uploads.first.file_name = "some-path/some-image.jpg"
Final Thoughts
See, no magic after all! You are now well equipped to have some fun on your own. There is certainly a bit more to learn about Nokogiri and Mechanize, but instead of spending too much time on unnecessary aspects, play around with it and look into some more documentation when you run into problems beyond the scope of a beginner article.
I hope you can see how beautifully simple this gem is and how much power it offers. As we all know from popular culture by now, this also bears responsibilities. Use it within legal frameworks and when you have no access to an API. You probably won’t have a frequent use for these tools, but boy do they come in handy when you have some real scraping needs ahead of you.
As promised, in the next article we will cover a real-world example where I will scrape data from my podcast site. I will extract it from an old Sinatra site and transfer it over to my new Middleman site that uses .markdown
files for each episode. We will extract the dates, episodes numbers, interviewee names, headers, subheaders, and so on. See you there!