Python Web Scraping — ওয়েব স্ক্রেপিং ( part — 2 )

this article is from udemy course Modern web scraping with python using scrapy splash selenium by Ahmed Rafik

প্রথম পর্ব এখানে নিচের লিঙ্কে ।

Content:

  • 5. Debugging spider
  • 6. Project-3 : Build Crawlers using Scrapy
  • 7. Splash crash course
  • 8. Project-4: Scraping Javascript websites using Splash

5. Debugging spider

spider এর অফিসিয়াল ডকুমেন্টেশনে বিভিন্ন ধরনের পদ্ধতি দেওয়া আছে , প্রথমে আমরা এগুলো দেখবো । এরপর আমরা আমাদের নিজস্ব পদ্ধতি দেখবো ।

documentation থেকে দেখা যায় যে parse একটি প্রসেস যেটার মাধ্যমে মেথডের নরমাল বিহেভিওর দেখা যায় , অনেকটা console.log() এর মতো । জাস্ট চেক করা যে আউটপুট ঠিক ঠাক ভাবে আসে কিনা । এখানে depth হচ্ছে এক প্রসেস থেকে আরেক প্রসেসে যেতে কয়টা ধাপ পার করতে হয় ।

আমাদের county প্রজেক্টে এটা ইমপ্লিমেন্ট করবো । এখানকার parse_country মেথডের name টা আসে parse() মেথডের meta র মাধ্যমে অর্থাৎ আমরা কোন দেশের ইনফরমেশন দেখতে চাচ্ছি সেটা এখানে পাস করে দিবো ।

এখানকার জন্য আমরা China এ ইনফরমেশন দেখবো । তাই নিচের কমান্ড টি ব্যাবহার করবো ।

$ scrapy parse --spider=countries -c parse_country --meta='{"country_name":"China"}' https://www.worldometers.info/world-population/china-population

দ্বিতীয় পদ্ধতি হচ্ছে scrapy shell এ ঢুকে চেক করা ।

from scrapy.shell import inspect_response

এই লাইন দিয়ে ইম্পরট করে নেই ।

এরপর ধরা যাক parse_country() মেথডের ভেতর সকল কোড comment out করে দিয়ে জাস্ট নিচের লাইন টুকু লিখি ।

inspect_response(response, self)

এখন কমান্ড লাইনের যেয়ে নিচের কমান্ড টি চালাই ।

scrapy crawl countries

এই কমান্ড দিলে shell এ ঢুকে যাবে এখান থেকে বিভিন্ন ধরনের কমান্ড চালিয়ে ডাটা চেক করতে পারি ।

> request.headers> response.body> view(response)

এছাড়াও log এবং warning ও একি ভাবে করা যায় । এটা আমরা ডকুমেন্টেশন থেকে দেখে নিতে পারি ।

এখন আমরা যেটা দেখবো সেটাই মূলত সব সময় ব্যাবহার করবো ।

এজন্য প্রথমে প্রজেক্টের রুট ডিরেক্টরিতে runner.py নামে একটি ফাইল তৈরি করে সেখানে কিছু কোড লিখি ।

import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from simple_project.spiders.countries import CountriesSpider
process = CrawlerProcess(settings=get_project_settings())
process.crawl(CountriesSpider)
process.start()

এরপর countries ফাইল এ যেয়ে যেখান থেকে ডিবাগ করতে চাই সেই লাইনের পাশে red color এর ডট এ ক্লিক করে ডিবাগ রান করলে দেখা যাবে ।

মূলত lead generation, real estate listings এরকম বিভিন্ন ধরনের কাজে web scraping ব্যাবহার করা হয় ।

6. Project-3 : Build Crawlers using Scrapy

scrapy তে বিভিন্ন ধরনের টেম্পলেট আছে আমরা এতক্ষণ basic টেম্পলেট ব্যাবহার করেছি । নিচের কমান্ড দিলে আমরা দেখতে পারবো যে কি কি টেম্পলেট আছে ।

scrapy genspider -l

প্রথমে একটি প্রজেক্ট তৈরি করি ।

$ scrapy startproject imdb
$ cd imdb
$ scrapy genspider -t crawl best_movies imdb.com

এখানে imdb নামে প্রজেক্ট তৈরি করে এটার spider তৈরি করেছি crawl টেম্পলেট ব্যাবহার করে , তাই এটার স্ত্রাকচার এ একটু ভিন্নতা আসবে ।

এখানে rules এ একাধিক tuple থাকতে পারে । এখানে rule এ allow এ একটি রেগুলার এক্সপ্রেশন ব্যাবহার করেছি , Items/ থাকলে এটা ফলো করবে এছাড়াও বিভিন্ন ধরনের জিনিস ব্যাবহার করা যায় ।

এই লিঙ্ক থেকে আমরা ডাটা স্ক্র্যাপ করবো ।

allow এর জায়গায় deny দেওয়া যায় , তখন এর মানে হবে এটা থাকলে ব্যাবহার করবো না। এছাড়াও xpath ব্যাবহারের জন্য erstrict_xpaths ব্যাবহার করা যায় আবার css selector এর জন্য restrict_css ব্যাবহার করা যায় ।

এখন নিচের কোড গুলো লিখে ডাটা নিয়ে আসবো ।

scrapy crawl best_movies -o movies.csv

এই কমান্ড রান করলে movies.csv ফাইলে ডাটাগুলো জমা হবে ।

এখন এখানে কিছু প্রব্লেম আছে প্রথমে utf এর সমস্যা, টেক্সট না দেখিয়ে utf দেখায় । এটার জন্য settings.py ফাইলে নিচের কমান্ডটি দিয়ে দিবো ।

FEED_EXPORT_ENCODING = 'utf-8'

দ্বিতীয়ত duration এ \n দিয়ে এক্সট্রা একটি লাইন প্রিন্ট করে এটা দূর করার জন্য নিচের মতো করে parse_item এ normalize-space() মেথডের ভেতর xpath এক্সপ্রেশন দিয়ে দিবো ।

'duration': response.xpath("normalize-space(//div[@class='subtext']/time/text())").get()

এখন পেজিনেসনের জন্য নতুন আরেকটি রুল তৈরি করতে হবে ।

Rule(LinkExtractor(restrict_xpaths="(//a[@class='lister-page-next next-page'])[2]"))

এভাবে দিলে আরও পেজ থাকলে সব গুলোর ডাটা নিয়ে আসবে , এখানে follow দেওয়া হয় নাই কারণ এর ডিফল্ট ভেলু true.

Modify User-Agent

user agent মডিফাই করার জন্য সেটিং থেকেও করা যায় কিন্তু আমরা এখানে spider ফাইল থেকে কিভাবে পরিবতন করবো সেটা দেখবো । এটা আমরা করবো best_movies.py ফাইল থেকে ।

google এ my user agent

লিখে সার্চ দিলে আমাদের কম্পিউটারের user agent চলে আসবে সেটা কপি করে নিবো । এরপর নিচের মতো করে লিখব ।

7. Splash crash course

splash install করার কমান্ড নিচের এই ডকুমেন্টেশনে দেওয়া আছে ।

$ sudo docker pull scrapinghub/splash
$ sudo docker run -it -p 8050:8050 --rm scrapinghub/splash

এটা রান করার পর localhost:8050 লোকাল host এ যেয়ে ইন্টার দিলে নিচের মতো পেজ ওপেন হবে ।

উপরের এই কোড বক্সে কোড লিখা হয় lua তে

এখানে আমরা কিছু কোড লিখেছি lua তে । lua cheat sheet এখানে

প্রথমে একটি ফাংশন লিখেছি, এই main ফাংশনটি সব সময় ই লিখতে হয় । এরপর url এর জায়গায় ইনপুটে কি দিয়েছে সেটা ধরার জন্য args.url দিয়েছি , এরপর সেই url এ যাওয়ার জন্য splash:go(url) দিয়েছি এরপর কি রিটার্ন করবে সেটা দিয়েছি, এখানকার জন্য আমরা ঐ সাইটের একটি স্কিন সর্ট নিয়েছে সেটার জন্য splash:png() দিয়েছি, আর শেষে end দিয়ে ফাংশন শেষ করেছি ।

এখন স্কিন সর্ট না নিয়ে এর পরিবর্তে html ও রিটার্ন করতে পারি সেজন্য splash:html() দিলেই হবে ।

যদি দুইটাই পেতে চাই তাহলে সেকেন্ড ব্রাকেটের মধ্যে দুইটাই দিয়ে দিতে হবে ।

return {
image = splash:png(),
html = splash:html()
}

এখন কোন এরর আসলে সেটাও দেখাবে ।

কিন্তু আমরা চাচ্ছি যে url এ কোন এরর দেখা দিলে তখন তখনি স্টপ হয়ে যাবে আর ফারদার এক্সিকিউট করবে না ।সেজন্য শুধু assert() ব্যাবহার করলেই হবে ।

assert(splash:go(url))

অনেক সময় পেজ লোড হতে কিছুটা সময় নেয় আর তাই রিটার্ন স্টেটমেন্টের কোড এক্সিইউট করার আগে কিছু সময় wait করবো এজন্য wait()মেথড ব্যাবহার করতে হয় ।

assert(splash:wait(1))

Working with element:

প্রথমে duckduckgo তে গিয়ে ইনপুট বক্সের id কপি করে নিয়েছি এরপর splash:select() মেথডের ভেতর id পাস করে দিয়েছি । এখানে আমরা ইচ্ছা করলে xpath expression ও ব্যাবহার করতে পারি । এছাড়াও আমরা এখানে class attribute না নিয়ে id নিয়েছি কারণ এটা রিকমান্ড করা যে id থাকলে আগে id নিতে হবে । এরপর সেটাকে focus করে send_text() এক যে ইনপুট টা দিবো সেটা পাঠিয়ে দিয়েছি ।

এখানে আমরা go বাটনে ক্লিক করে সার্চ করেছি কিন্তু আমরা এখন Enter বাটন ক্লিক করে সার্চ করবো ।

--[[ ]]-- এটা দিয়ে কমেন্ট বোঝানো হয়েছে এরপর key input দেওয়ার জন্য send_keys() এর ভেতরে কী পাঠানো যায় এরপর এর ভেতর কী পাঠানোর জন্য "<>" ডাবল কোটের মধ্যে দুইটা <> দিতে হয় ।

আর set_viewport_full() এটার মানে হচ্ছে যে আমরা ফুল পেজ দেখতে চাচ্ছি ।

Spoofing request header :

প্রথমে যেটা করেছি splash:set_user_agent() এটা দিয়ে শুধু মাত্র একটা রিকোয়েস্টের user agent মডিফাই করা যায়, এরপরের টা একাধিক header মডিফাই করা যায় । আর শেষেরটা splash:on_request() এটা দিয়ে প্রত্যেক রিকোয়েস্টের সাথে modified hedar পাঠানো যায় ।

Full code here ….

8. Project-4: Scraping Javascript websites using Splash

splash দিয়ে জাভাস্ক্রিপ্টেড সাইট স্ক্র্যাপ করা হয় কারণ নেক্সট পেজে যাওয়ার বাটনে অনেক সময় বা অন্য যেকোনো জায়গায় জাভাস্ক্রিপ্ট দিয়ে ডায়নামিক ভাবে কাজ করে বা ট্যাব এর ক্ষেত্রে , এসব জায়গায় নরমাল scrapy দিয়ে কাজ করা যায় না তখন আমরা splash / selenium দিয়ে কাজ করতে হয় । selenium হচ্ছে অটোমেশন টুল এটা পরবর্তীতে স্ক্রেপিং এর কাজে ব্যাবহার করা হয় , মূলত splash ই স্ক্রেপিং এর কাজ করার জন্য তৈরি করা হয়েছে ।

private_mode_enabled এর ডিফল্ট ভেলু true থাকে , এটা থাকলে অনেক সময় এক্সপেক্টেড ভেলু দেয় না, এটা অনেক টা আমাদের ব্রাউজারের incognito mode এর মতো । এটা প্রথমে false করে দিয়েছি এরপ url নিয়ে কল করেছি, এরপর যে ট্যাবে ক্লিক করবো সেই ট্যাবের id নিয়েছি , একি id অনেক কয়টা আছে সেখান থেকে 5 নাম্বার id নিয়ে সেটাকে ক্লিক করেছি ।

এখন splash দিয়ে javascript প্রজেক্ট স্ক্র্যাপ করার জন্য প্রথমে একটি প্রজেক্ট তৈরি করতে হবে ।

$ scrapy startproject livecoin

এরপর প্রজেক্টের ভেতরে যেয়ে নিচের কমান্ড টি দিয়ে coin নামে একটি spider তৈরি করবো ।

এরপর নিচের এই লিঙ্কে যাবো ।

এখানে সব ইন্সট্রাকশন দেওয়া আছে ।

এখন প্রথমে scrapy-splash ইন্সটল করবো ।

pip install scrapy-splash

এরপর terminal splash রান করে রাখবো ।

$ docker run -p 8050:8050 scrapinghub/splash

এরপর settings.py ফাইলে নিচের লাইনটি দিয়ে দিবো, এই url টি ধরিয়ে দেওয়ার জন্য ।

SPLASH_URL = 'http://localhost:8050'

এরপর download middleware দিয়ে দিবো ।

DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}

এরপর spider middleware দিবো ।

SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}

এরপর duplicate class দিবো ।

DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'

এরপর coin স্পাইডারে যেয়ে নিচের কোড গুলো দিবো allowed_domains এর পরে ।

এখন coin.py স্পাইডারে নিচের কোড গুলো লিখবো ।