セレン(ざくざく)でデータをスクレーピングするシリーズ


こんにちは!


アップグレードシリーズの2番目のポストへようこそ!まず第一に、私は本当に私のポストとYouTubeチャンネルであなたの支持と親切を評価します.パイソンについてのより涼しい内容を作成するために私を動機づけてくれてありがとう.
あなたがここに新しいならば、すぐに私にあなたの新しいブランドを紹介させてください.このチャンネルの主な違いは-私は“初心者のためのJSのチュートリアル”や“Pythonのチュートリアル”などの退屈なものを教えていないこのようなものは、本当に古いと便利ではありません.代わりに、私はあなたのポートフォリオとあなたの将来のキャリアを向上させる現実世界のアプリケーションを見せている.私を信じて、あなたは失望されません!
また、Reverse Pythonのウェブアプリケーションをチェックしてください
とにかく、十分に話して、この新しいupworkプロジェクトを構築しましょう!

人間の遅延によるウェブサイトからのデータのスクレーピング


ご覧のように、私たちの新しい仕事はウェブサイトからいくつかのデータを削ることです.残念なことに、これは普通のウェブサイトではないので、私たちは別のメルトされたHTML構造に直面するつもりです.

ステップ1:タスクを理解する


したがって、我々のタスクは、ターゲットページを移動し、データをクロールし、Excelシートにエクスポートすることです.我々のオートメーションは、検出と他のどんなサーバーエラーも避けるために、人間の遅れでなければなりません.
Click to see Job Posting
クライアントは、明示的に手順を記述するジョブの投稿の下にPDF添付ファイルを提供しました.以下にタスクの説明を示します.

I need help setting up a web scraper that gets data from a website. What I need it to do is:

  • Enter the website and navigate to "Sök kungörelse"
  • Navigate to "Avancerad sökning" (Advanced search)
  • Apply following filters from following:
  • - Tidsperiod > Annan period > Input date-interval for the past day - Ämnesområde > Bolagsverkets registreringar - Kungörelserubrik > Aktiebolagsregistret - Underrubrik > Nyregistreringar
  • Submit by pressing "Sök"
  • Enter all the listings that show up
  • Get text for: "Postadress", "Bildat" "Företagsnamn" and "E-post"
  • Export data to Google Sheets or an Excel Sheet daily. I also need this crawler to have some human delay so it doesn't crash the website or give burden to the server.

私たちの最終目的地は「postadress」、「bildat」、f - purretsnamn、e - postのデータをクロールすることになります.

Step 2 :環境の作成と依存関係のインストール


今、我々はクライアントが何を望んでいるかを知っているので、私たちの仮想環境を作成してから、我々はクロールしようとしている要素を検査しましょう.
仮想コンソールを作成するには、次のコマンドを端末で実行します.
virtualenv env
. env/bin/activate
これらのライブラリをインストールします.
pip install selenium xlwt
あなたが知っているように、セレンはWebオートメーションツールです、そして、我々は目標ページをナビゲートして、そこからデータを得るためにそれを使うつもりです.XLWTは、マイクロソフトExcelと互換性のあるスプレッドシートファイルを生成するためのライブラリであり、パッケージ自体は、標準のPythonディストリビューション以外のモジュールやパッケージに依存しない純粋なPythonです.
私は、あなたの何人かがパンダを使うように言うということを知っています、しかし、ちょうどこのプロジェクトのためにXLWTを保ちましょう.

ステップ3:データのナビゲーションとクロール


Webドライバを正しく設定することが重要です.ChromeをWebドライバとして使用する場合は、chromedriverをインストールする必要があります.ただし、Firefoxを選択する場合は、geckodriverをインストールする必要があります.
あなたが毎回各機能でウェブドライバーをつくる必要がないように、簡単にURLと呼び出し機能を取り扱うクラスをつくることから始めましょう.
from selenium import webdriver

class Bolagsverket:

    def __init__(self):
        # set your driver path here
        self.bot = webdriver.Firefox(executable_path='/path/to/geckodriver')
プロジェクトURL click hereを見るには
さて、NavigateHandとCrownという名前の新しい関数を作成します.
import time

def navigate_and_crawl(self):
        bot = self.bot
        bot.get('https://poit.bolagsverket.se/poit/PublikPoitIn.do') 
        time.sleep(5)
ご覧のように、私は人の遅れのように行動するためにURLに移動した後、sleep ()関数を右に置きます.

ウェブサイトを入力し、“S



この要素を検査しましょう

def navigate_and_crawl(self):
        bot = self.bot
        bot.get('https://poit.bolagsverket.se/poit/PublikPoitIn.do') 
        time.sleep(5)
        bot.find_element_by_id('nav1-2').click()
        time.sleep(5)
単にIDを見つけた後、リンクをクリックします.

「Avancerad s Around King」へのナビゲート



今、我々は“高度な検索”リンクをクリックする必要があります.

あなたが見るように、1つのアンカータグがフォームにあるので、特定のIDまたはクラスで要素を見つける必要はありません.
    def navigate_and_crawl(self):
        bot = self.bot
        bot.get('https://poit.bolagsverket.se/poit/PublikPoitIn.do') 
        time.sleep(5)
        bot.find_element_by_id('nav1-2').click()
        time.sleep(5)
        bot.find_element_by_tag_name('form').find_element_by_tag_name('a').click()
        time.sleep(5)
私は再びXPathを使用するように私に言っている何人かの賢い人々を聞いています.それは完全に罰金です、私はちょうど詳細を示すためにより簡単にしようとしています.

フィルタの適用と検索


-過去の日の入力日付間隔
<資料>所蔵品の所蔵品
<研究ノート>リューブリューブリクの思想
- Underrubrik > Nyregistreringar

我々は、過去の日の日付間隔を設定する必要がありますが、現在のところ、過去の日のデータがないので、私は上記の画像として日付を設定します.しかし、私はまた、どのように過去の日の間隔を設定するには、おそらくときにデータがあることを確認して表示されます.
コードの前に、見てみましょう.
-過去の日の入力日付間隔

大丈夫!今、私はドロップダウンオプションをクリックしてあなたに最高の解決策の一つを示すつもりです.
search_form = bot.find_element_by_tag_name('form')
search_form.find_element_by_xpath(f"//select[@id='tidsperiod']/option[text()='Annan period']").click()                                  
“アナン期間”を選択した後、日付フィールドが表示されますが、これらの日付フィールドが表示されるまでWebdriverを待つように明示的に待機する必要があることを意味します.

import datetime
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

    def navigate_and_crawl(self):
        bot = self.bot
        bot.get('https://poit.bolagsverket.se/poit/PublikPoitIn.do') 
        time.sleep(5)
        bot.find_element_by_id('nav1-2').click()
        time.sleep(5)
        bot.find_element_by_tag_name('form').find_element_by_tag_name('a').click()
        time.sleep(5)

        search_form = bot.find_element_by_tag_name('form')
        search_form.find_element_by_xpath(f"//select[@id='tidsperiod']/option[text()='Annan period']").click()                       
        wait = WebDriverWait(bot, 10)
        input_from = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@id='from']")))
        #input_from.send_keys(str(datetime.date.today()-datetime.timedelta(1)))
        input_from.send_keys('2019-09-23')
        input_to = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@id='tom']")))
        #input_to.send_keys(str(datetime.date.today()))
        input_to.send_keys('2019-09-24')
        time.sleep(3)
実際には、ドロップダウンから何かを選択するたびにフォームがリフレッシュされます.つまり、要素をクリックするときに待ちます.
<資料>所謂Bolagsverkets Registreringarについて
<研究ノート>リューサーブリブリクの思想
Underrubrik > Nyregistreringar
我々は、“アナン時代”を選択するために使用された同じ方法を適用しています.しかし、この時間を待つ追加.
すべての値を選択したら、フォームの下の[検索]ボタンをクリックします.
        amnesomrade = wait.until(EC.element_to_be_clickable((By.XPATH, "//select[@id='amnesomrade']")))
        amnesomrade.find_element_by_xpath(f"//select[@id='amnesomrade']/option[text()='Bolagsverkets registreringar']").click()
        time.sleep(2)
        kungorelserubrik = wait.until(EC.element_to_be_clickable((By.XPATH, "//select[@id='kungorelserubrik']")))
        kungorelserubrik.find_element_by_xpath(f"//select[@id='kungorelserubrik']/option[text()='Aktiebolagsregistret']").click()
        time.sleep(2)
        underrubrik = wait.until(EC.element_to_be_clickable((By.XPATH, "//select[@id='underrubrik']")))
        underrubrik.find_element_by_xpath(f"//select[@id='underrubrik']/option[text()='Nyregistreringar']").click()                             
        time.sleep(2)
        # Search Button 
        button_sok = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@id='SokKungorelse']")))
        button_sok.click()
        time.sleep(5)                                                

リストを繰り返してデータをクロールする


一度検索した結果、次のように表示されます

自動化はリストから結果を連続的にクリックしなければなりません、クリックされたページのデータをクロールして、結果に再び戻ってください、そして、次に、すべての年齢が終わるまで、次の結果をクリックしてください.
クライアントが言及したように、各ページのExcelシートでデータを保存する必要があります.
すべてのページの数と各ページの結果の数を見つけることから始めましょう
あなたが上の写真の最初の赤い円を見るならば、我々が合計18ページを持っていることを意味する最後のページの数を見ることができます.

# find number of pages and extract the string after "av"
number_of_pages = bot.find_element_by_xpath('//div[@class="gotopagediv"]/em[@class="gotopagebuttons"]').text.split("av",1)[1] 
# remove any empty spaces                           
number_of_pages.strip().replace(" ", "")
# all results or links for each page
number_of_results = bot.find_elements_by_xpath('//table/tbody/tr')
そして今、ページと結果を繰り返してリスト内の各リンクまたは結果をクリックします.
また、各ページの新しいExcelシートを作成する必要があります.覚えておいてください、私たちは「ポストアドレス」、「bildat」、「f - str retretsnamn」と「電子メール」をクロールしなければなりません
wb = Workbook() 
for page in range(int(number_of_pages)):
    # Create new sheet for each page
    sheet = wb.add_sheet('Sheet ' + str(page)) 
    style = xlwt.easyxf('font: bold 1') 
    sheet.write(0, 0, 'Post Address', style) 
    sheet.write(0, 1, 'Bildat', style) 
    sheet.write(0, 2, 'Företagsnamn', style)
    sheet.write(0, 3, 'Email', style)
    # Click each link in results
    for i in range(1, len(number_of_results) + 1):
        result = bot.find_elements_by_xpath('//table/tbody/tr')[i]
        link = result.find_element_by_tag_name('a')
        bot.execute_script("arguments[0].click();", link)
        time.sleep(2)
ご覧のように、我々は以前に文字列として抽出したので、ページ数を少しずつ整数に変換しています.JavaScriptを使用している理由は、リンクがクリックされたことを確認することです.
今、これらのリンク内のデータをクロールする時間.

要素を検査するとき:

これらの特定のフィールドを抽出する特別なクラスやIDはありません.この種のケースでは、私はストリングからデータを抽出するためにregexを使用しています.
私はこの部分の完全なコードブロックを示しています.
wb = Workbook() 
for page in range(int(number_of_pages)):
    sheet = wb.add_sheet('Sheet ' + str(page), cell_overwrite_ok=True) 
    style = xlwt.easyxf('font: bold 1') 
    sheet.write(0, 0, 'Post Address', style) 
    sheet.write(0, 1, 'Bildat', style) 
    sheet.write(0, 2, 'Företagsnamn', style)
    sheet.write(0, 3, 'Email', style)
    for i in range(len(number_of_results)):
        result = bot.find_elements_by_xpath('//table/tbody/tr')[i]
        link = result.find_element_by_tag_name('a')
        bot.execute_script("arguments[0].click();", link)
        time.sleep(2)
        information = [bot.find_element_by_class_name('kungtext').text]
        try:
            postaddress = re.search('Postadress:(.*),', information[0])
            sheet.write(i + 1, 0, str(postaddress.group(1))) 
            bildat = re.search('Bildat:(.*)\n', information[0])
            sheet.write(i + 1, 1, str(bildat.group(1))) 
            foretagsnamn = re.search('Företagsnamn:(.*)\n', information[0])
            sheet.write(i + 1, 2, str(foretagsnamn .group(1))) 
            email = re.search('E-post:(.*)\n', information[0])
            sheet.write(i + 1, 3, str(email.group(1))) 
            print(postaddress.group(1),bildat.group(1),foretagsnamn.group(1),email.group(1))
        except AttributeError as e:
            print('error => Email is null')
            sheet.write(i + 1, 3, 'null') 
            pass
        bot.back()
        time.sleep(5)
        wb.save('emails.xls') 
    print('Going to next page') 
    button_next= wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@id='movenextTop']")))
    button_next.click()
    time.sleep(5)

regexは段落の「フィールド名」と「\n」改行の間の値を抽出します.いくつかの結果で電子メールフィールドが不足しているので、私はそれを検出し、自動的にフィールドを“null”を設定してくださいを試して追加しました.
i + 1はExcelセルの列名を上書きするのを防いでいます.私は非常に詳細な説明のために私のYouTubeチャンネルをチェックすることをお勧めします.
1ページのプログラムに成功した場合、データをシートに保存し、次のページに移動します.

フルコード


import time
import datetime
import re
import xlwt
from xlwt import Workbook
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC 
from selenium.webdriver.support.ui import WebDriverWait

class Bolagsverket:

    def __init__(self):
        self.bot = webdriver.Firefox(executable_path='/home/coderasha/Desktop/geckodriver')


    def navigate_and_crawl(self):
        bot = self.bot
        bot.get('https://poit.bolagsverket.se/poit/PublikPoitIn.do')
        time.sleep(5)
        bot.find_element_by_id('nav1-2').click()
        time.sleep(5)
        bot.find_element_by_tag_name('form').find_element_by_tag_name('a').click()
        time.sleep(5)

        search_form = bot.find_element_by_tag_name('form')
        search_form.find_element_by_xpath("//select[@id='tidsperiod']/option[text()='Annan period']").click()
        wait = WebDriverWait(bot, 10)
        input_from = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@id='from']")))
        input_from.send_keys('2019-09-23')
        # input_from.send_keys(str(datetime.date.today()-datetime.timedelta(1)))
        input_to = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@id='tom']")))
        input_to.send_keys('2019-09-24')
        # input_to.send_keys(str(datetime.date.today()))
        time.sleep(5)

        amnesomrade = wait.until(EC.element_to_be_clickable((By.XPATH, "//select[@id='amnesomrade']")))
        amnesomrade.find_element_by_xpath("//select[@id='amnesomrade']/option[text()='Bolagsverkets registreringar']").click()
        time.sleep(5)
        kungorelserubrik = wait.until(EC.element_to_be_clickable((By.XPATH, "//select[@id='kungorelserubrik']")))
        kungorelserubrik.find_element_by_xpath("//select[@id='kungorelserubrik']/option[text()='Aktiebolagsregistret']").click()
        time.sleep(5)
        underrubrik = wait.until(EC.element_to_be_clickable((By.XPATH, "//select[@id='underrubrik']")))
        underrubrik.find_element_by_xpath("//select[@id='underrubrik']/option[text()='Nyregistreringar']").click()

        # Search Button
        button_sok = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@id='SokKungorelse']")))
        button_sok.click()
        time.sleep(5)

        number_of_pages = bot.find_element_by_xpath("//div[@class='gotopagediv']/em[@class='gotopagebuttons']").text.split("av", 1)[1]                         
        number_of_pages.strip().replace(" ","")

        number_of_results = bot.find_elements_by_xpath('//table/tbody/tr')

        wb = Workbook()
        for page in range(int(number_of_pages)):
            sheet = wb.add_sheet('Sheet' + str(page))
            style = xlwt.easyxf('font: bold 1')
            sheet.write(0, 0, 'Post Address', style)
            sheet.write(0, 1, 'Bildat', style)
            sheet.write(0, 2, 'Foretagsnamn', style)
            sheet.write(0, 3, 'Email', style)

            for i in range(len(number_of_results)):
                result = bot.find_elements_by_xpath("//table/tbody/tr")[i]
                link = result.find_element_by_tag_name('a')
                bot.execute_script('arguments[0].click();', link)
                time.sleep(5)

                information = [bot.find_element_by_class_name('kungtext').text]
                try:
                    postaddress = re.search('Postadress:(.*),', information[0])
                    sheet.write(i + 1, 0, str(postaddress.group(1)))
                    bildat = re.search('Bildat:(.*)\n', information[0])
                    sheet.write(i + 1, 1, str(bildat.group(1)))
                    foretagsnamn = re.search('Företagsnamn:(.*)\n', information[0])
                    sheet.write(i + 1, 2, str(foretagsnamn.group(1)))
                    email = re.search('E-post:(.*)\n', information[0])
                    sheet.write(i + 1, 3, str(email.group(1)))
                    print(postaddress.group(1), bildat.group(1), foretagsnamn.group(1), email.group(1))
                except AttributeError as e:
                    print('Email is null')
                    sheet.write(i + 1, 3, 'null')
                    pass
                bot.back()
                time.sleep(5)
                wb.save('emails.xls')
            print('Going to next page ...')
            button_next = wait.until(EC.element_to_be_clickable((By.XPATH, "//input/[@id='movenextTop']")))
            button_next.click()
            time.sleep(5)


bot = Bolagsverket()
bot.navigate_and_crawl()

任務完了!


このプロジェクトのビデオチュートリアルを見ることができます
私はあなたが楽しんで、このポストから何かを学んだことを願っています.仕事はまだ開いているので、あなたはupworkからクライアントに提案を送ることができます.このようなより涼しい内容のためにReverse Pythonをチェックしてください.接続を維持!