Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි

අද අප පළ කරන ලිපියේ පරිවර්තනය වන ලිපියේ කතුවරයා පවසන්නේ ගුවන් ටිකට්පත් මිල ගණන් සොයන Selenium භාවිතා කරමින් Python හි වෙබ් scraper එකක් සංවර්ධනය කිරීම ගැන කතා කිරීම එහි අරමුණ බවයි. ප්‍රවේශපත්‍ර සෙවීමේදී නම්‍යශීලී දින භාවිතා කරනු ලැබේ (නිශ්චිත දින වලට සාපේක්ෂව දින +-3). scraper සෙවුම් ප්‍රතිඵල Excel ගොනුවක සුරකින අතර සෙවුම ක්‍රියාත්මක කළ පුද්ගලයාට ඔවුන් සොයාගත් දේ පිළිබඳ සාරාංශයක් සහිත විද්‍යුත් තැපෑලක් යවයි. මෙම ව්‍යාපෘතියේ අරමුණ වන්නේ සංචාරකයින්ට හොඳම ගනුදෙනු සොයා ගැනීමට උපකාර කිරීමයි.

Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි

ද්‍රව්‍ය තේරුම් ගැනීමේදී, ඔබට අහිමි බවක් දැනේ නම්, බලන්න මේ ලිපිය.

අපි සොයන්නේ කුමක් ද?

ඔබට අවශ්‍ය පරිදි මෙහි විස්තර කර ඇති පද්ධතිය භාවිතා කිරීමට ඔබට නිදහස ඇත. උදාහරණයක් ලෙස, මම සති අන්ත සංචාර සහ මගේ උපන් නගරයට ප්‍රවේශපත් සෙවීමට එය භාවිතා කළෙමි. ඔබ ලාභදායී ප්‍රවේශපත්‍ර සොයා ගැනීම ගැන බැරෑරුම් නම්, ඔබට සේවාදායකයේ ස්ක්‍රිප්ට් ධාවනය කළ හැකිය (සරල සේවාදායකය, මසකට රූබල් 130 ක් සඳහා, මේ සඳහා බෙහෙවින් සුදුසු ය) සහ එය දිනකට වරක් හෝ දෙවරක් ධාවනය වන බවට වග බලා ගන්න. සෙවුම් ප්‍රතිඵල ඔබට විද්‍යුත් තැපෑලෙන් එවනු ලැබේ. ඊට අමතරව, ස්ක්‍රිප්ට් එක ඩ්‍රොප්බොක්ස් ෆෝල්ඩරයක සෙවුම් ප්‍රතිඵල සහිත Excel ගොනුවක් සුරකින පරිදි සෑම දෙයක්ම සැකසීමට මම නිර්දේශ කරමි, එමඟින් ඔබට එවැනි ගොනු ඕනෑම තැනක සිට ඕනෑම වේලාවක බැලීමට ඉඩ සලසයි.

Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි
මම තවමත් දෝෂ සහිත තීරුබදු සොයාගෙන නැත, නමුත් එය හැකි බව මම සිතමි

සෙවීමේදී, දැනටමත් සඳහන් කර ඇති පරිදි, "නම්‍යශීලී දිනයක්" භාවිතා කරනු ලැබේ; ලබා දී ඇති දිනවලින් දින තුනක් ඇතුළත පිරිනැමීම් ස්ක්‍රිප්ට් සොයා ගනී. ස්ක්‍රිප්ට් ධාවනය කරන විට, එය එක් දිශාවකට පමණක් දීමනා සොයන නමුත්, එය පියාසර දිශාවන් කිහිපයක දත්ත රැස් කිරීමට හැකි වන පරිදි එය වෙනස් කිරීම පහසුය. එහි ආධාරයෙන්, ඔබට වැරදි ගාස්තු සොයා බැලිය හැකිය; එවැනි සොයාගැනීම් ඉතා සිත්ගන්නා සුළු විය හැකිය.

ඔබට වෙනත් වෙබ් scraper අවශ්ය වන්නේ ඇයි?

මම මුලින්ම වෙබ් සීරීම් ආරම්භ කරන විට, මම අවංකවම ඒ ගැන විශේෂ උනන්දුවක් දැක්වූයේ නැත. පුරෝකථන ආකෘති නිර්මාණය, මූල්‍ය විශ්ලේෂණ ක්ෂේත්‍රයේ සහ, සමහර විට, පෙළෙහි චිත්තවේගීය වර්ණ ගැන්වීමේ ක්‍ෂේත්‍රයේ තවත් ව්‍යාපෘති කිරීමට මට අවශ්‍ය විය. නමුත් වෙබ් අඩවි වලින් දත්ත එකතු කරන වැඩසටහනක් නිර්මාණය කරන්නේ කෙසේදැයි සොයා බැලීම ඉතා සිත්ගන්නා සුළු බව පෙනී ගියේය. මම මෙම මාතෘකාව ගැන සොයා බලන විට, වෙබ් සීරීම් යනු අන්තර්ජාලයේ "එන්ජිම" බව මට වැටහුණි.

මෙය නිර්භීත ප්‍රකාශයක් යැයි ඔබට සිතෙන්නට පුළුවන. නමුත් Google පටන් ගත්තේ Larry Page විසින් Java සහ Python යොදාගෙන නිර්මාණය කරන ලද web scraper එකකින් බව සලකන්න. ගූගල් රොබෝවරු අන්තර්ජාලය ගවේෂණය කරමින් එහි පරිශීලකයින්ට ඔවුන්ගේ ප්‍රශ්නවලට හොඳම පිළිතුරු ලබා දීමට උත්සාහ කරති. වෙබ් සීරීමට නිමක් නැති ප්‍රයෝජන ඇති අතර, ඔබ දත්ත විද්‍යාවේ වෙනත් දෙයක් ගැන උනන්දු වුවද, ඔබට විශ්ලේෂණය කිරීමට අවශ්‍ය දත්ත ලබා ගැනීමට ඔබට යම් යම් සීරීම් කුසලතා අවශ්‍ය වනු ඇත.

මෙහි භාවිතා කර ඇති සමහර ශිල්පීය ක්‍රම අපූරු ලෙස මට හමු විය පොත මම මෑතකදී අත්පත් කරගත් web scraping ගැන. ඔබ ඉගෙන ගත් දේ ප්‍රායෝගිකව භාවිතා කිරීම සඳහා බොහෝ සරල උදාහරණ සහ අදහස් එහි අඩංගු වේ. මීට අමතරව, reCaptcha චෙක්පත් මඟ හැරීම පිළිබඳ ඉතා රසවත් පරිච්ඡේදයක් ඇත. එවැනි ගැටළු විසඳීම සඳහා විශේෂ මෙවලම් සහ සම්පූර්ණ සේවාවන් පවා ඇති බව මා නොදැන සිටි බැවින් මෙය මට ප්‍රවෘත්තියක් විය.

ඔබ සංචාරය කිරීමට කැමතිද?!

මෙම කොටසේ මාතෘකාවේ ඇති සරල හා තරමක් හානිකර නොවන ප්‍රශ්නයට, එය අසන ලද පුද්ගලයාගේ සංචාර වලින් කථා කිහිපයක් සමඟ ධනාත්මක පිළිතුරක් ඔබට බොහෝ විට ඇසෙනු ඇත. සංචාරය කිරීම නව සංස්කෘතික පරිසරයන් තුළ ගිල්වීමට සහ ඔබේ සීමාවන් පුළුල් කිරීමට විශිෂ්ට මාර්ගයක් බව අප බොහෝ දෙනා එකඟ වනු ඇත. කෙසේ වෙතත්, ඔබ ගුවන් ටිකට්පත් සෙවීමට කැමතිදැයි ඔබ යමෙකුගෙන් ඇසුවහොත්, පිළිතුර එතරම් ධනාත්මක නොවන බව මට විශ්වාසයි. ඇත්ත වශයෙන්ම, පයිතන් මෙහි අපගේ උදව්වට පැමිණේ.

ගුවන් ටිකට්පත් පිළිබඳ තොරතුරු සෙවීම සඳහා පද්ධතියක් නිර්මාණය කිරීම සඳහා අප විසින් විසඳිය යුතු පළමු කාර්යය වනුයේ අප තොරතුරු ලබා ගන්නා සුදුසු වේදිකාවක් තෝරා ගැනීමයි. මෙම ගැටලුව විසඳීම මට පහසු නොවූ නමුත් අවසානයේ මම Kayak සේවාව තෝරා ගත්තෙමි. මම Momondo, Skyscanner, Expedia සහ තවත් කිහිප දෙනෙකුගේ සේවාවන් අත්හදා බැලුවෙමි, නමුත් මෙම සම්පත් මත රොබෝ ආරක්ෂණ යාන්ත්‍රණ අපරාජිත විය. මාර්ග ලයිට්, පදික මාරුවීම් සහ බයිසිකල් සමඟ කටයුතු කිරීමට මට සිදු වූ උත්සාහයන් කිහිපයකින් පසු, මා මිනිසෙකු බව පද්ධති ඒත්තු ගැන්වීමට උත්සාහ කිරීමෙන් පසු, පිටු විශාල ප්‍රමාණයක් පටවා තිබුණද, කයාක් මට වඩාත් සුදුසු බව මම තීරණය කළෙමි. කෙටි කාලයක් තුළ, සහ චෙක්පත් ද ආරම්භ වේ. මම bot පැය 4 සිට 6 දක්වා කාලය තුළ වෙබ් අඩවියට ඉල්ලීම් යැවීමට සමත් වූ අතර, සියල්ල හොඳින් ක්‍රියාත්මක විය. වරින් වර, Kayak සමඟ වැඩ කිරීමේදී දුෂ්කරතා පැන නගී, නමුත් ඔවුන් ඔබට චෙක්පත් සමඟ කරදර කිරීමට පටන් ගන්නේ නම්, ඔබ ඔවුන් සමඟ අතින් ගනුදෙනු කර පසුව bot දියත් කළ යුතුය, නැතහොත් පැය කිහිපයක් රැඳී සිට චෙක්පත් නතර කළ යුතුය. අවශ්‍ය නම්, ඔබට වෙනත් වේදිකාවක් සඳහා කේතය පහසුවෙන් අනුවර්තනය කළ හැකි අතර, ඔබ එසේ කරන්නේ නම්, ඔබට එය අදහස් දැක්වීමේදී වාර්තා කළ හැකිය.

ඔබ වෙබ් සීරීම් කිරීම ආරම්භ කරන්නේ නම් සහ සමහර වෙබ් අඩවි එය සමඟ අරගල කරන්නේ මන්දැයි නොදන්නේ නම්, ඔබ මෙම ප්‍රදේශයේ ඔබේ පළමු ව්‍යාපෘතිය ආරම්භ කිරීමට පෙර, ඔබටම උදව්වක් කර "වෙබ් සීරීම් ආචාර විධි" යන වචන මත ගූගල් සෙවුමක් කරන්න. . ඔබ අඥාන ලෙස වෙබ් සීරීම් සිදු කරන්නේ නම් ඔබේ අත්හදා බැලීම් ඔබ සිතනවාට වඩා ඉක්මනින් අවසන් විය හැක.

ආරම්භ කිරීම

මෙන්න අපගේ වෙබ් scraper කේතයේ කුමක් සිදුවේද යන්න පිළිබඳ සාමාන්‍ය දළ විශ්ලේෂණයක්:

  • අවශ්‍ය පුස්තකාල ආනයනය කරන්න.
  • Google Chrome ටැබ් එකක් විවෘත කිරීම.
  • ප්‍රවේශපත්‍ර සෙවීමේදී භාවිතා කරන නගර සහ දිනයන් පසුකර බොට් ආරම්භ කරන ශ්‍රිතයක් අමතන්න.
  • මෙම ශ්‍රිතය පළමු සෙවුම් ප්‍රතිඵල ගෙන, හොඳම ලෙස වර්ග කර, තවත් ප්‍රතිඵල පූරණය කිරීමට බොත්තමක් ක්ලික් කරයි.
  • තවත් කාර්යයක් සම්පූර්ණ පිටුවෙන් දත්ත රැස් කර දත්ත රාමුවක් ලබා දෙයි.
  • පෙර පියවර දෙක ප්‍රවේශපත්‍ර මිල (ලාභ) සහ පියාසැරි වේගය (වේගවත්ම) අනුව වර්ග කිරීම භාවිතා කර සිදු කෙරේ.
  • ස්ක්‍රිප්ට් භාවිතා කරන්නාට ප්‍රවේශපත්‍ර මිල (ලාභම ප්‍රවේශපත්‍ර සහ සාමාන්‍ය මිල) සාරාංශයක් අඩංගු විද්‍යුත් තැපෑලක් යවනු ලබන අතර, ඉහත සඳහන් දර්ශක තුනෙන් වර්ග කරන ලද තොරතුරු සහිත දත්ත රාමුවක් Excel ගොනුවක් ලෙස සුරකිනු ලැබේ.
  • ඉහත සඳහන් සියලු ක්රියාවන් නිශ්චිත කාල සීමාවකට පසුව චක්රයක් තුල සිදු කරනු ලැබේ.

සෑම Selenium ව්යාපෘතියක්ම වෙබ් ධාවකයකින් ආරම්භ වන බව සැලකිල්ලට ගත යුතුය. මම පාවිච්චි කරනවා Chromedriver, මම Google Chrome සමඟ වැඩ කරනවා, නමුත් වෙනත් විකල්ප තිබේ. PhantomJS සහ Firefox ද ජනප්‍රියයි. ධාවක බාගත කිරීමෙන් පසු, ඔබ එය සුදුසු ෆෝල්ඩරයේ තැබිය යුතු අතර, මෙය එහි භාවිතය සඳහා සූදානම් වීම සම්පූර්ණ කරයි. අපගේ ස්ක්‍රිප්ටයේ පළමු පේළි නව Chrome ටැබ් එකක් විවෘත කරයි.

මගේ කතාවේ මම ගුවන් ටිකට්පත් සඳහා විශාල ගනුදෙනු සෙවීම සඳහා නව ක්ෂිතිජයක් විවෘත කිරීමට උත්සාහ නොකරන බව මතක තබා ගන්න. එවැනි දීමනා සෙවීමේ වඩාත් දියුණු ක්‍රම තිබේ. මෙම ගැටළුව විසඳීම සඳහා සරල නමුත් ප්‍රායෝගික ක්‍රමයක් මෙම ද්‍රව්‍යයේ පාඨකයන්ට පිරිනැමීමට මට අවශ්‍යය.

මෙන්න අපි ඉහත කතා කළ කේතය.

from time import sleep, strftime
from random import randint
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import smtplib
from email.mime.multipart import MIMEMultipart

# Используйте тут ваш путь к chromedriver!
chromedriver_path = 'C:/{YOUR PATH HERE}/chromedriver_win32/chromedriver.exe'

driver = webdriver.Chrome(executable_path=chromedriver_path) # Этой командой открывается окно Chrome
sleep(2)

කේතයේ ආරම්භයේදී ඔබට අපගේ ව්‍යාපෘතිය පුරාවටම භාවිතා කරන පැකේජ ආනයන විධානයන් දැකිය හැක. ඒ නිසා, randint නව සෙවුම් මෙහෙයුමක් ආරම්භ කිරීමට පෙර අහඹු තත්පර ගණනක් සඳහා බොට් "නින්දට" පත් කිරීමට භාවිතා කරයි. සාමාන්‍යයෙන් එක බොට් එකකටවත් මේක නැතුව කරන්න බෑ. ඔබ ඉහත කේතය ධාවනය කරන්නේ නම්, ක්‍රෝම් කවුළුවක් විවෘත වනු ඇත, එය අඩවි සමඟ වැඩ කිරීමට බොට් භාවිතා කරයි.

අපි පොඩි අත්හදා බැලීමක් කරලා kayak.com වෙබ් අඩවිය වෙනම කවුළුවකින් විවෘත කරමු. අපි පියාසර කිරීමට යන නගරය සහ අපට යාමට අවශ්‍ය නගරය මෙන්ම ගුවන් ගමන් දිනයන් ද අපි තෝරා ගනිමු. දිනයන් තෝරාගැනීමේදී, +-3 දින පරාසය භාවිතා කරන බවට වග බලා ගන්න. එවැනි ඉල්ලීම් වලට ප්‍රතිචාර වශයෙන් වෙබ් අඩවිය නිපදවන දේ සැලකිල්ලට ගනිමින් මම කේතය ලිව්වෙමි. උදාහරණයක් ලෙස, ඔබට නිශ්චිත දිනයන් සඳහා පමණක් ප්‍රවේශපත්‍ර සෙවීමට අවශ්‍ය නම්, ඔබට බොට් කේතය වෙනස් කිරීමට සිදුවනු ඇති බවට ඉහළ සම්භාවිතාවක් ඇත. මම කේතය ගැන කතා කරන විට, මම සුදුසු පැහැදිලි කිරීම් සපයනවා, නමුත් ඔබට ව්‍යාකූල බවක් දැනෙනවා නම්, මට දන්වන්න.

දැන් සෙවුම් බොත්තම ක්ලික් කර ලිපින තීරුවේ ඇති සබැඳිය බලන්න. එය විචල්‍යය ප්‍රකාශ කර ඇති පහත උදාහරණයේ මා භාවිතා කරන සබැඳියට සමාන විය යුතුය kayak, URL එක ගබඩා කරන, සහ ක්‍රමය භාවිතා කරයි get වෙබ් ධාවකය. සෙවුම් බොත්තම ක්ලික් කිරීමෙන් පසුව, ප්රතිඵල පිටුවේ දිස්විය යුතුය.

Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි
මම විධානය භාවිතා කළ විට get මිනිත්තු කිහිපයක් ඇතුළත දෙතුන් වතාවකට වඩා, reCaptcha භාවිතයෙන් සත්‍යාපනය සම්පූර්ණ කරන ලෙස මගෙන් ඉල්ලා සිටියේය. ඔබට මෙම චෙක්පත අතින් සම්මත කර පද්ධතිය නව චෙක්පතක් ක්‍රියාත්මක කිරීමට තීරණය කරන තෙක් අත්හදා බැලීම දිගටම කරගෙන යා හැක. මම ස්ක්‍රිප්ට් එක පරීක්‍ෂා කළ විට, පළමු සෙවුම් සැසිය සෑම විටම සුමටව සිදු වූ බව පෙනුණි, එබැවින් ඔබට කේතය සමඟ අත්හදා බැලීමට අවශ්‍ය නම්, ඔබට සිදු වන්නේ සෙවුම් සැසි අතර දිගු කාල පරතරයන් භාවිතා කරමින් වරින් වර අතින් පරීක්ෂා කර කේතය ක්‍රියාත්මක කිරීමට ඉඩ දීම පමණි. තවද, ඔබ ඒ ගැන සිතන්නේ නම්, සෙවුම් මෙහෙයුම් අතර මිනිත්තු 10 ක පරතරයකින් ලැබෙන ටිකට් මිල පිළිබඳ තොරතුරු පුද්ගලයෙකුට අවශ්‍ය නොවේ.

XPath භාවිතයෙන් පිටුවක් සමඟ වැඩ කිරීම

ඉතින්, අපි කවුළුවක් විවෘත කර වෙබ් අඩවිය පටවා ඇත. මිලකරණය සහ අනෙකුත් තොරතුරු ලබා ගැනීම සඳහා, අපි XPath තාක්ෂණය හෝ CSS තේරීම් භාවිතා කළ යුතුය. මම XPath සමඟ රැඳී සිටීමට තීරණය කළ අතර CSS තේරීම් භාවිතා කිරීමේ අවශ්‍යතාවයක් දැනුණේ නැත, නමුත් එය එසේ ක්‍රියා කිරීමට බෙහෙවින් හැකි ය. XPath භාවිතයෙන් පිටුවක් වටා සැරිසැරීම උපක්‍රමශීලී විය හැකි අතර, ඔබ මා විස්තර කළ තාක්ෂණික ක්‍රම භාවිතා කළත් මේ පිටු කේතයෙන් අනුරූප හඳුනාගැනීම් පිටපත් කිරීම සම්බන්ධ වූ ලිපිය, මෙය ඇත්ත වශයෙන්ම අවශ්‍ය අංග වෙත ප්‍රවේශ වීමට ප්‍රශස්ත ක්‍රමය නොවන බව මට වැටහුණි. මාර්ගය වන විට, තුළ මේ XPath සහ CSS තේරීම් භාවිතා කරමින් පිටු සමඟ වැඩ කිරීමේ මූලික කරුණු පිළිබඳ විශිෂ්ට විස්තරයක් මෙම පොත සපයයි. අනුරූප වෙබ් ධාවක ක්‍රමය පෙනෙන්නේ මෙයයි.

Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි
ඉතින්, අපි බොට් එකේ වැඩ දිගටම කරගෙන යමු. ලාභම ප්‍රවේශපත්‍ර තෝරා ගැනීමට වැඩසටහනේ හැකියාවන් භාවිතා කරමු. පහත රූපයේ, XPath තේරීම් කේතය රතු පැහැයෙන් උද්දීපනය කර ඇත. කේතය බැලීම සඳහා, ඔබ කැමති පිටු මූලද්‍රව්‍යය මත දකුණු-ක්ලික් කර දිස්වන මෙනුවෙන් Inspect විධානය තෝරාගත යුතුය. මෙම විධානය විවිධ පිටු මූලද්‍රව්‍ය සඳහා කැඳවිය හැක, එහි කේතය කේත නරඹන්නා තුළ දර්ශනය වන අතර උද්දීපනය කෙරේ.

Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි
පිටු කේතය බලන්න

කේතයෙන් තේරීම්කරුවන් පිටපත් කිරීමේ අවාසි පිළිබඳ මගේ තර්කය තහවුරු කිරීම සඳහා, පහත විශේෂාංග වෙත අවධානය යොමු කරන්න.

ඔබ කේතය පිටපත් කරන විට ඔබට ලැබෙන්නේ මෙයයි:

//*[@id="wtKI-price_aTab"]/div[1]/div/div/div[1]/div/span/span

මෙවැනි දෙයක් පිටපත් කිරීම සඳහා, ඔබ කැමති කේතයේ කොටස මත දකුණු-ක්ලික් කර දිස්වන මෙනුවෙන් Copy > Copy XPath විධානය තෝරාගත යුතුය.

ලාභම බොත්තම නිර්වචනය කිරීමට මා භාවිතා කළේ මෙන්න:

cheap_results = ‘//a[@data-code = "price"]’

Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි
විධානය පිටපත් කරන්න > XPath පිටපත් කරන්න

දෙවන විකල්පය වඩා සරල බව පෙනේ. භාවිතා කරන විට, එය ගුණාංගය ඇති මූලද්‍රව්‍යයක් සොයයි data-codeසමානයි price. පළමු විකල්පය භාවිතා කරන විට, මූලද්රව්යය සොයනු ලැබේ id සමාන වන wtKI-price_aTab, සහ මූලද්‍රව්‍ය වෙත XPath මාර්ගය දිස්වේ /div[1]/div/div/div[1]/div/span/span. පිටුවකට මෙවැනි XPath විමසුමක් උපක්‍රම කරයි, නමුත් එක් වරක් පමණි. ඒක මට දැන්ම කියන්න පුළුවන් id ඊළඟ වතාවේ පිටුව පූරණය වන විට වෙනස් වනු ඇත. චරිත අනුපිළිවෙල wtKI පිටුව පූරණය වන සෑම අවස්ථාවකම ගතිකව වෙනස් වේ, එබැවින් එය භාවිතා කරන කේතය ඊළඟ පිටුව නැවත පූරණය කිරීමෙන් පසුව නිෂ්ඵල වනු ඇත. එබැවින් XPath තේරුම් ගැනීමට යම් කාලයක් ගත කරන්න. මෙම දැනුම ඔබට හොඳින් සේවය කරනු ඇත.

කෙසේ වෙතත්, XPath තේරීම් පිටපත් කිරීම තරමක් සරල වෙබ් අඩවි සමඟ වැඩ කිරීමේදී ප්රයෝජනවත් විය හැකි බව සැලකිල්ලට ගත යුතු අතර, ඔබ මෙය සමඟ සැපපහසු නම්, එහි කිසිදු වරදක් නැත.

ලැයිස්තුවක් ඇතුලේ සියලුම සෙවුම් ප්‍රතිඵල පේළි කිහිපයකින් ලබා ගැනීමට අවශ්‍ය නම් කුමක් කළ යුතු දැයි දැන් අපි සිතමු. හරිම සරලයි. සෑම ප්‍රතිඵලයක්ම පන්තියක් සහිත වස්තුවක් තුළ ඇත resultWrapper. සියලුම ප්‍රතිඵල පූරණය කිරීම පහත දැක්වෙන ආකාරයට සමාන ලූපයකින් කළ හැක.

ඔබ ඉහත කරුණු තේරුම් ගන්නේ නම්, අපි විශ්ලේෂණය කරන බොහෝ කේතයන් ඔබට පහසුවෙන් තේරුම් ගත යුතු බව සැලකිල්ලට ගත යුතුය. මෙම කේතය ක්‍රියාත්මක වන විට, අපට අවශ්‍ය දේට (ඇත්ත වශයෙන්ම, ප්‍රති result ලය ඔතා ඇති මූලද්‍රව්‍යය) යම් ආකාරයක මාර්ග-නිශ්චිත යාන්ත්‍රණයක් (XPath) භාවිතා කර ප්‍රවේශ කරමු. මෙය සිදු කරනුයේ මූලද්‍රව්‍යයේ පෙළ ලබාගෙන එය දත්ත කියවිය හැකි වස්තුවක තැබීම සඳහාය (පළමුව භාවිතා flight_containers, ඉන්පසු - flights_list).

Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි
පළමු පේළි තුන දර්ශනය වන අතර අපට අවශ්ය සියල්ල පැහැදිලිව දැකගත හැකිය. කෙසේ වෙතත්, අපට තොරතුරු ලබා ගැනීම සඳහා වඩාත් රසවත් ක්රම තිබේ. අපි එක් එක් මූලද්‍රව්‍ය වලින් වෙන වෙනම දත්ත ගත යුතුයි.

වැඩට!

ශ්‍රිතයක් ලිවීමට ඇති පහසුම ක්‍රමය නම් අමතර ප්‍රතිඵල පූරණය කිරීමයි, ඒ නිසා අපි ආරම්භ කරන්නම්. පරීක්ෂණයකට තුඩු දෙන සේවාවේ සැකයන් ඇති නොකර, වැඩසටහනට තොරතුරු ලැබෙන ගුවන් ගමන් ගණන උපරිම කිරීමට මම කැමතියි, එබැවින් පිටුව දර්ශනය වන සෑම අවස්ථාවකම මම වැඩි ප්‍රතිඵල පූරණය කරන්න බොත්තම ක්ලික් කරන්නෙමි. මෙම කේතය තුළ, ඔබ අවහිර කිරීමට අවධානය යොමු කළ යුතුය try, සමහර වෙලාවට බොත්තම හරියට ලෝඩ් වෙන්නේ නැති නිසා මම එකතු කළා. ඔබටත් මෙය හමු වුවහොත්, මෙම ශ්‍රිතයට ලැබෙන ඇමතුම් ශ්‍රිත කේතයෙන් අදහස් දක්වන්න start_kayak, අපි පහත බලමු.

# Загрузка большего количества результатов для того, чтобы максимизировать объём собираемых данных
def load_more():
    try:
        more_results = '//a[@class = "moreButton"]'
        driver.find_element_by_xpath(more_results).click()
        # Вывод этих заметок в ходе работы программы помогает мне быстро выяснить то, чем она занята
        print('sleeping.....')
        sleep(randint(45,60))
    except:
        pass

දැන්, මෙම ශ්‍රිතය පිළිබඳ දීර්ඝ විශ්ලේෂණයකින් පසුව (සමහර විට මා රැගෙන යා හැක), පිටුව සීරීමට ලක් කරන ශ්‍රිතයක් ප්‍රකාශ කිරීමට අපි සූදානම්.

පහත සඳහන් ශ්‍රිතයේ අවශ්‍ය බොහෝ දේ මම දැනටමත් එකතු කර ඇත page_scrape. සමහර වෙලාවට රිටන් පාත් දත්ත එකතු වෙන නිසා මම ඒක වෙන් කරන්න සරල ක්‍රමයක් භාවිතා කරනවා. උදාහරණයක් ලෙස, මම පළමු වරට විචල්යයන් භාවිතා කරන විට section_a_list и section_b_list. අපගේ කාර්යය දත්ත රාමුවක් ලබා දෙයි flights_df, විවිධ දත්ත වර්ග කිරීමේ ක්‍රම වලින් ලබාගත් ප්‍රතිඵල වෙන්කර පසුව ඒවා ඒකාබද්ධ කිරීමට මෙය අපට ඉඩ සලසයි.

def page_scrape():
    """This function takes care of the scraping part"""
    
    xp_sections = '//*[@class="section duration"]'
    sections = driver.find_elements_by_xpath(xp_sections)
    sections_list = [value.text for value in sections]
    section_a_list = sections_list[::2] # так мы разделяем информацию о двух полётах
    section_b_list = sections_list[1::2]
    
    # Если вы наткнулись на reCaptcha, вам может понадобиться что-то предпринять.
    # О том, что что-то пошло не так, вы узнаете исходя из того, что вышеприведённые списки пусты
    # это выражение if позволяет завершить работу программы или сделать ещё что-нибудь
    # тут можно приостановить работу, что позволит вам пройти проверку и продолжить скрапинг
    # я использую тут SystemExit так как хочу протестировать всё с самого начала
    if section_a_list == []:
        raise SystemExit
    
    # Я буду использовать букву A для уходящих рейсов и B для прибывающих
    a_duration = []
    a_section_names = []
    for n in section_a_list:
        # Получаем время
        a_section_names.append(''.join(n.split()[2:5]))
        a_duration.append(''.join(n.split()[0:2]))
    b_duration = []
    b_section_names = []
    for n in section_b_list:
        # Получаем время
        b_section_names.append(''.join(n.split()[2:5]))
        b_duration.append(''.join(n.split()[0:2]))

    xp_dates = '//div[@class="section date"]'
    dates = driver.find_elements_by_xpath(xp_dates)
    dates_list = [value.text for value in dates]
    a_date_list = dates_list[::2]
    b_date_list = dates_list[1::2]
    # Получаем день недели
    a_day = [value.split()[0] for value in a_date_list]
    a_weekday = [value.split()[1] for value in a_date_list]
    b_day = [value.split()[0] for value in b_date_list]
    b_weekday = [value.split()[1] for value in b_date_list]
    
    # Получаем цены
    xp_prices = '//a[@class="booking-link"]/span[@class="price option-text"]'
    prices = driver.find_elements_by_xpath(xp_prices)
    prices_list = [price.text.replace('$','') for price in prices if price.text != '']
    prices_list = list(map(int, prices_list))

    # stops - это большой список, в котором первый фрагмент пути находится по чётному индексу, а второй - по нечётному
    xp_stops = '//div[@class="section stops"]/div[1]'
    stops = driver.find_elements_by_xpath(xp_stops)
    stops_list = [stop.text[0].replace('n','0') for stop in stops]
    a_stop_list = stops_list[::2]
    b_stop_list = stops_list[1::2]

    xp_stops_cities = '//div[@class="section stops"]/div[2]'
    stops_cities = driver.find_elements_by_xpath(xp_stops_cities)
    stops_cities_list = [stop.text for stop in stops_cities]
    a_stop_name_list = stops_cities_list[::2]
    b_stop_name_list = stops_cities_list[1::2]
    
    # сведения о компании-перевозчике, время отправления и прибытия для обоих рейсов
    xp_schedule = '//div[@class="section times"]'
    schedules = driver.find_elements_by_xpath(xp_schedule)
    hours_list = []
    carrier_list = []
    for schedule in schedules:
        hours_list.append(schedule.text.split('n')[0])
        carrier_list.append(schedule.text.split('n')[1])
    # разделяем сведения о времени и о перевозчиках между рейсами a и b
    a_hours = hours_list[::2]
    a_carrier = carrier_list[1::2]
    b_hours = hours_list[::2]
    b_carrier = carrier_list[1::2]

    
    cols = (['Out Day', 'Out Time', 'Out Weekday', 'Out Airline', 'Out Cities', 'Out Duration', 'Out Stops', 'Out Stop Cities',
            'Return Day', 'Return Time', 'Return Weekday', 'Return Airline', 'Return Cities', 'Return Duration', 'Return Stops', 'Return Stop Cities',
            'Price'])

    flights_df = pd.DataFrame({'Out Day': a_day,
                               'Out Weekday': a_weekday,
                               'Out Duration': a_duration,
                               'Out Cities': a_section_names,
                               'Return Day': b_day,
                               'Return Weekday': b_weekday,
                               'Return Duration': b_duration,
                               'Return Cities': b_section_names,
                               'Out Stops': a_stop_list,
                               'Out Stop Cities': a_stop_name_list,
                               'Return Stops': b_stop_list,
                               'Return Stop Cities': b_stop_name_list,
                               'Out Time': a_hours,
                               'Out Airline': a_carrier,
                               'Return Time': b_hours,
                               'Return Airline': b_carrier,                           
                               'Price': prices_list})[cols]
    
    flights_df['timestamp'] = strftime("%Y%m%d-%H%M") # время сбора данных
    return flights_df

මම විචල්‍යයන් නම් කිරීමට උත්සාහ කළෙමි, එවිට කේතය තේරුම් ගත හැකිය. විචල්‍යයන් ආරම්භ වන බව මතක තබා ගන්න a මාර්ගයේ පළමු අදියරට අයත් වේ, සහ b - දෙවැන්නට. අපි ඊළඟ කාර්යයට යමු.

ආධාරක යාන්ත්රණ

අපට දැන් අමතර සෙවුම් ප්‍රතිඵල පූරණය කිරීමට ඉඩ සලසන කාර්යයක් සහ එම ප්‍රතිඵල සැකසීමට ශ්‍රිතයක් ඇත. ඔබටම විවෘත කළ හැකි පිටු සීරීමට අවශ්‍ය සියල්ල මෙම කාර්යයන් දෙක මඟින් සපයන බැවින් මෙම ලිපිය මෙතැනින් අවසන් විය හැක. නමුත් ඉහත සාකච්ඡා කළ සමහර සහායක යාන්ත්‍රණ අපි තවමත් සලකා බැලුවේ නැත. උදාහරණයක් ලෙස, මෙය ඊමේල් යැවීම සහ වෙනත් දේවල් සඳහා කේතය වේ. මේ සියල්ල කාර්යයේ සොයාගත හැකිය start_kayak, අපි දැන් සලකා බලමු.

මෙම කාර්යයට නගර සහ දිනයන් පිළිබඳ තොරතුරු අවශ්‍ය වේ. මෙම තොරතුරු භාවිතා කරමින්, එය විචල්‍යයක සබැඳියක් සාදයි kayak, එය විමසුමට ඔවුන්ගේ හොඳම ගැළපීම අනුව වර්ග කරන ලද සෙවුම් ප්‍රතිඵල අඩංගු පිටුවකට ඔබව ගෙන යාමට භාවිතා කරයි. පළමු සීරීම් සැසියෙන් පසු, අපි පිටුවේ ඉහළින් ඇති වගුවේ මිල ගණන් සමඟ වැඩ කරන්නෙමු. එනම්, අපි අවම ටිකට් මිල සහ සාමාන්ය මිල සොයා ගනිමු. මේ සියල්ල, වෙබ් අඩවිය විසින් නිකුත් කරන ලද අනාවැකි සමඟ, ඊමේල් මගින් යවනු ලැබේ. පිටුවෙහි, අනුරූප වගුව ඉහළ වම් කෙළවරේ විය යුතුය. මෙම වගුව සමඟ වැඩ කිරීම, නිශ්චිත දිනයන් භාවිතා කරමින් සෙවීමේදී දෝෂයක් ඇති කළ හැකිය, මන්ද මෙම අවස්ථාවේදී වගුව පිටුවේ නොපෙන්වයි.

def start_kayak(city_from, city_to, date_start, date_end):
    """City codes - it's the IATA codes!
    Date format -  YYYY-MM-DD"""
    
    kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to +
             '/' + date_start + '-flexible/' + date_end + '-flexible?sort=bestflight_a')
    driver.get(kayak)
    sleep(randint(8,10))
    
    # иногда появляется всплывающее окно, для проверки на это и его закрытия можно воспользоваться блоком try
    try:
        xp_popup_close = '//button[contains(@id,"dialog-close") and contains(@class,"Button-No-Standard-Style close ")]'
        driver.find_elements_by_xpath(xp_popup_close)[5].click()
    except Exception as e:
        pass
    sleep(randint(60,95))
    print('loading more.....')
    
#     load_more()
    
    print('starting first scrape.....')
    df_flights_best = page_scrape()
    df_flights_best['sort'] = 'best'
    sleep(randint(60,80))
    
    # Возьмём самую низкую цену из таблицы, расположенной в верхней части страницы
    matrix = driver.find_elements_by_xpath('//*[contains(@id,"FlexMatrixCell")]')
    matrix_prices = [price.text.replace('$','') for price in matrix]
    matrix_prices = list(map(int, matrix_prices))
    matrix_min = min(matrix_prices)
    matrix_avg = sum(matrix_prices)/len(matrix_prices)
    
    print('switching to cheapest results.....')
    cheap_results = '//a[@data-code = "price"]'
    driver.find_element_by_xpath(cheap_results).click()
    sleep(randint(60,90))
    print('loading more.....')
    
#     load_more()
    
    print('starting second scrape.....')
    df_flights_cheap = page_scrape()
    df_flights_cheap['sort'] = 'cheap'
    sleep(randint(60,80))
    
    print('switching to quickest results.....')
    quick_results = '//a[@data-code = "duration"]'
    driver.find_element_by_xpath(quick_results).click()  
    sleep(randint(60,90))
    print('loading more.....')
    
#     load_more()
    
    print('starting third scrape.....')
    df_flights_fast = page_scrape()
    df_flights_fast['sort'] = 'fast'
    sleep(randint(60,80))
    
    # Сохранение нового фрейма в Excel-файл, имя которого отражает города и даты
    final_df = df_flights_cheap.append(df_flights_best).append(df_flights_fast)
    final_df.to_excel('search_backups//{}_flights_{}-{}_from_{}_to_{}.xlsx'.format(strftime("%Y%m%d-%H%M"),
                                                                                   city_from, city_to, 
                                                                                   date_start, date_end), index=False)
    print('saved df.....')
    
    # Можно следить за тем, как прогноз, выдаваемый сайтом, соотносится с реальностью
    xp_loading = '//div[contains(@id,"advice")]'
    loading = driver.find_element_by_xpath(xp_loading).text
    xp_prediction = '//span[@class="info-text"]'
    prediction = driver.find_element_by_xpath(xp_prediction).text
    print(loading+'n'+prediction)
    
    # иногда в переменной loading оказывается эта строка, которая, позже, вызывает проблемы с отправкой письма
    # если это прозошло - меняем её на "Not Sure"
    weird = '¯_(ツ)_/¯'
    if loading == weird:
        loading = 'Not sure'
    
    username = '[email protected]'
    password = 'YOUR PASSWORD'

    server = smtplib.SMTP('smtp.outlook.com', 587)
    server.ehlo()
    server.starttls()
    server.login(username, password)
    msg = ('Subject: Flight Scrapernn
Cheapest Flight: {}nAverage Price: {}nnRecommendation: {}nnEnd of message'.format(matrix_min, matrix_avg, (loading+'n'+prediction)))
    message = MIMEMultipart()
    message['From'] = '[email protected]'
    message['to'] = '[email protected]'
    server.sendmail('[email protected]', '[email protected]', msg)
    print('sent email.....')

මම Outlook ගිණුමක් (hotmail.com) භාවිතයෙන් මෙම ස්ක්‍රිප්ට් පරීක්ෂා කළෙමි. Gmail ගිණුමක් සමඟ නිවැරදිව වැඩ කිරීමට මම එය පරීක්‍ෂා කර නැත, මෙම විද්‍යුත් තැපැල් පද්ධතිය බෙහෙවින් ජනප්‍රියයි, නමුත් හැකි විකල්ප බොහොමයක් තිබේ. ඔබ Hotmail ගිණුමක් භාවිතා කරන්නේ නම්, සෑම දෙයක්ම ක්‍රියාත්මක වීමට නම්, ඔබ ඔබේ දත්ත කේතයට ඇතුළත් කළ යුතුය.

මෙම කාර්යය සඳහා කේතයේ නිශ්චිත කොටස්වල හරියටම සිදු කරන්නේ කුමක්ද යන්න තේරුම් ගැනීමට ඔබට අවශ්ය නම්, ඔබට ඒවා පිටපත් කර ඒවා සමඟ අත්හදා බැලීම් කළ හැකිය. කේතය සමඟ අත්හදා බැලීම එය සැබවින්ම තේරුම් ගැනීමට ඇති එකම මාර්ගයයි.

සූදානම් පද්ධතිය

දැන් අපි කතා කරපු හැම දෙයක්ම කරලා ඉවරයි, අපිට පුළුවන් සරල ලූප් එකක් හදාගන්න ඒකෙන් අපේ කර්තව්‍යයන් හඳුන්වනවා. ස්ක්‍රිප්ට් පරිශීලකයාගෙන් නගර සහ දිනයන් පිළිබඳ දත්ත ඉල්ලා සිටී. ස්ක්‍රිප්ට් අඛණ්ඩව නැවත ආරම්භ කිරීම සමඟින් පරීක්‍ෂා කරන විට, ඔබට මෙම දත්ත සෑම විටම අතින් ඇතුළත් කිරීමට අවශ්‍ය නොවනු ඇත, එබැවින් පරීක්‍ෂණ කාලය සඳහා අනුරූප රේඛා, ඒවාට අවශ්‍ය දත්ත ඒවාට පහළින් අදහස් දැක්වීමෙන් ඉවත් කිරීමෙන් අදහස් දැක්විය හැකිය. script එක hardcode කර ඇත.

city_from = input('From which city? ')
city_to = input('Where to? ')
date_start = input('Search around which departure date? Please use YYYY-MM-DD format only ')
date_end = input('Return when? Please use YYYY-MM-DD format only ')

# city_from = 'LIS'
# city_to = 'SIN'
# date_start = '2019-08-21'
# date_end = '2019-09-07'

for n in range(0,5):
    start_kayak(city_from, city_to, date_start, date_end)
    print('iteration {} was complete @ {}'.format(n, strftime("%Y%m%d-%H%M")))
    
    # Ждём 4 часа
    sleep(60*60*4)
    print('sleep finished.....')

ස්ක්‍රිප්ට් එකේ පරීක්ෂණ ධාවනයක් පෙනෙන්නේ මෙයයි.
Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි
පිටපතේ පරීක්ෂණ ධාවනය

ප්රතිඵල

ඔබ එය මෙතරම් දුරට සමත් වූවා නම්, ඔබට සුබ පැතුම්! ඔබට දැන් වැඩ කරන වෙබ් සීරීම් යන්ත්‍රයක් ඇත, නමුත් එය වැඩිදියුණු කිරීමට මට දැනටමත් බොහෝ ක්‍රම දැකිය හැකිය. උදාහරණයක් ලෙස, එය Twilio සමඟ ඒකාබද්ධ කළ හැකි අතර එමඟින් ඊමේල් වෙනුවට කෙටි පණිවිඩ යවනු ලැබේ. සර්වර් කිහිපයකින් එකවර ප්‍රතිඵල ලබාගැනීමට ඔබට VPN එකක් හෝ වෙනත් දෙයක් භාවිත කළ හැක. ඔහු පුද්ගලයෙක් දැයි බැලීමට වෙබ් අඩවිය භාවිතා කරන්නා පරීක්ෂා කිරීමේදී වරින් වර පැන නගින ගැටළුවක් ද ඇත, නමුත් මෙම ගැටළුව ද විසඳිය හැකිය. ඕනෑම අවස්ථාවක, දැන් ඔබට අවශ්‍ය නම් පුළුල් කළ හැකි පදනමක් තිබේ. උදාහරණයක් ලෙස, Excel ගොනුවක් ඊමේල් එකකට ඇමුණුමක් ලෙස පරිශීලකයාට යවා ඇති බවට වග බලා ගන්න.

Python - සංචාරය කිරීමට කැමති අය සඳහා මිල අඩු ගුවන් ටිකට්පත් සොයා ගැනීමට සහායකයෙකි

සමීක්ෂණයට සහභාගී විය හැක්කේ ලියාපදිංචි පරිශීලකයින්ට පමණි. පුරන්නකරුණාකර.

ඔබ වෙබ් සීරීම් තාක්ෂණය භාවිතා කරනවාද?

  • බව

  • කිසිදු

පරිශීලකයින් 8 දෙනෙක් ඡන්දය දුන්හ. 1 පරිශීලකයෙක් වැළකී සිටියේය.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න