Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Amazonのログイン情報を保持したい

環境

MAC OS: MAC OS Movajave
言語:python3.8
モジュール一覧

beautifulsoup4      4.9.3
certifi             2020.11.8
chardet             3.0.4
chromedriver-binary 87.0.4280.20.0
click               7.1.2
cssselect           1.1.0
idna                2.10
isodate             0.6.0
lxml                4.6.2
parsel              1.6.0
pip                 20.3.1
ppprint             0.1.0
pyparsing           2.4.7
PyYAML              5.3.1
rdflib              5.0.0
requests            2.25.0
selectorlib         0.16.0
selenium            3.141.0
setuptools          49.2.1
six                 1.15.0
soupsieve           2.1
SPARQLWrapper       1.8.5
urllib3             1.26.2
w3lib               1.22.0

発生している問題・エラー

クローリングの流れ
1. chromeで「amazon」と検索
2. amazonのURLをクリック
3. amazonにログイン
4. kindle本紹介ページ一覧画面に遷移
5. 一覧ページのhtmlデーターをbeautifulSoupに渡す。
6. ページのスクレピング

手順5のところで詰まっています。

navigateメソッドで該当ページのURLが返されます。
そしてresponseに該当ページのデーターが帰ってくるのですが、ログイン情報が保持されていない状態のページが返されます。

ログイン情報を保持した状態でページが返されてきて欲しいです。

該当するソースコード

import requests
import logging
import time
from selenium.webdriver import Chrome, ChromeOptions

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

from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
import csv
import pdb
from bs4 import BeautifulSoup


psward = 'パスワード'
search = "amazon"
email = 'メールアドレス'

def main():

    options = ChromeOptions()
    driver = Chrome(options=options) 

    actions = ActionChains(driver)

    url = navigate(driver, actions)
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    contents = scrape_content_for_login(soup)
    # write_to_csv(contents)


def navigate(driver, actions):

    logging.info('Navigating...')
    driver.get('https://www.google.co.jp/')

    # ---pythonを検索
    search_window = driver.find_element_by_name('q')
    search_window.send_keys(search)
    search_window.send_keys(Keys.ENTER)
    driver.find_element_by_css_selector('#tads > div > div > div > div.d5oMvf > a > div.cfxYMc.JfZTW.c4Djg.MUxGbd.v0nnCb').click()

    #ログイン
    flag = login(driver)

    # ---メニューをクリック
    source = driver.find_element_by_id('nav-hamburger-menu')
    source.click()
    time.sleep(2)
    #---
    target =driver.find_element_by_id('hmenu-content')

    #--開いたメニューにカーソルを合わせる。
    actions.click_and_hold(source)
    actions.move_to_element(target)
    actions.perform()
    time.sleep(2)
    #---

    i = 0
    for _ in range(10):
        i += 1
        print(i)
        #ログインした場合
        if flag:
            category = driver.find_element_by_css_selector('#hmenu-content > ul.hmenu.hmenu-visible > li:nth-child(14) > a')
        else:
        #ログインしていない場合    
            category = driver.find_element_by_css_selector('#hmenu-content > ul.hmenu.hmenu-visible > li:nth-child(13) > a')
        print(category.text)
        if category.text == 'Kindle 本&電子書籍リーダー': 
            category.click()
            break
        else:
            time.sleep(3)
            actions.click_and_hold(source)
            actions.move_to_element(target)
            actions.perform()
            time.sleep(3)

    driver.find_element_by_css_selector('#hmenu-content > ul.hmenu.hmenu-visible.hmenu-translateX > li:nth-child(10) > a').click()


    driver.find_element_by_css_selector('#a-page > div.a-container > div.a-row.apb-browse-two-col-center-pad > div.a-column.a-span12.aok-float-right.apb-browse-col-pad-left.apb-browse-two-col-center-margin-right > div:nth-child(4) > div:nth-child(3) > div.a-row.a-spacing-micro.a-spacing-top-mini.dbs-widget-head.a-ws-row > div.a-column.a-span3.a-text-right.a-ws-span4.dbs-widget-head-see-all.a-span-last.a-ws-span-last > a').click()

    WebDriverWait(driver, 30).until(EC.visibility_of_element_located)

    url = driver.current_url
    pdb.set_trace()
    return url


def scrape_content_for_login(soup):

    logging.info('scraping.....')
    contents = []

    for book in soup.select('#browse-grid-view > div.browse-clickable-item'):

        print(book)
    pdb.set_trace()
    #     title = book.select_one('span > div > span > a > div.p13n-sc-truncate').get_text(strip=True)
    #     price = book.select_one('span.p13n-sc-price').get_text(strip=True)
    #     try:
    #         popular = book.select_one('div.a-icon-row.a-spacing-none > a.a-size-small.a-link-normal').get_text(strip=True)
    #     except:
    #         popular = '評価無し'

    #     contents.append({


#
    #         'popular':popular,
    #     })
    #     # print(title)
    #     # print(price)
    #     # print(popular)
    # logging.info(f'scraped {len(contents)} data')
    # return contents




def scrape_content_for_unlogin(soup):

    logging.info('scraping.....')
    contents = []

    for book in soup.select('#zg-ordered-list > li.zg-item-immersion'):
        title = book.select_one('span > div > span > a > div.p13n-sc-truncate').get_text(strip=True)
        price = book.select_one('span.p13n-sc-price').get_text(strip=True)
        try:
            popular = book.select_one('div.a-icon-row.a-spacing-none > a.a-size-small.a-link-normal').get_text(strip=True)
        except:
            popular = '評価無し'

        contents.append({
            'title':title,
            'price':price,
            'popular':popular,
        })

    logging.info(f'scraped {len(contents)} data')
    return contents




def login(driver):
    element = driver.find_element_by_css_selector('.nav-action-inner')
    #JavaScriptを呼びだして無理やりクリック
    driver.execute_script('arguments[0].click();', element)

    element = driver.find_element_by_id('ap_email')
    element.send_keys(email)
    driver.find_element_by_id('continue').click()

    element = driver.find_element_by_id('ap_password')
    element.send_keys(psward)

    driver.find_element_by_id('signInSubmit').click()
    driver.execute_script('window.alert("この後携帯に送られる認証リンクをクリックしてください。");', element)
    time.sleep(10)
    return True


def write_to_csv(contents):

    header = ['title', 'price', 'popular']

    with open('./reommended-books.csv', 'w',newline='', encoding='shift-jis') as f:
        writer = csv.DictWriter(f, header)
        writer.writeheader()
        for content in contents:
                writer.writerow(content)



if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    main()



自分で試したこと

その1
chromeアカウントにログインした状態でamazonのリンクを踏めば、自動的にログインされるのではないかと思いchromeにログインしようとしましたがダメでした。
ソフトウェアによって制御されているブラウザーからはログイン出来ないみたいです。

スクリーンショット 2021-01-03 11.20.50.png

その2
以下のコードを追加してみましたが、ログイン出来ませんでした。
参考にしたページ: Python + Selenium + Chrome で自動ログインいくつか

options = webdriver.ChromeOptions()
options.add_argument('--user-data-dir=Users\\<ユーザ名>\\AppData\\Local\\Google\\Chrome\\User Data')
options.add_argument('--profile-directory=Profile 2')  # この行を省略するとDefaultフォルダが指定されます

driver = webdriver.Chrome(options=options)

長文になってしまい申し訳ありません。
何かわかる方、ご教授いただければ幸いです。

0

2Answer

webサーバはログインした端末にアクセストークン(たいていはcookie)を渡します。
そしてアクセストークンを添付していないリクエストは未ログイン端末からのリクエストとして扱います。
だからログイン後にしか取得できない情報は、ログインしたプログラム(たいていはブラウザ)からしか取得できません。

参考:【Python3】ログイン機能付サイトでスクレイピング【requests】【BeautifulSoup】

1Like

Comments

  1. @yonaimineakio

    Questioner

    コメントありがとうございます!
    ご提供いただいた記事を参考にして引き続きもがきます。

mainメソッドにSessionを追加しました。
またnavigateメソッドにクッキー情報を更新するプログラムを追加しました。

これによりログイン情報を引き継いだページを取得する事が出来ました。

以下の記事が参考になりました。
https://stackoverrun.com/ja/q/8991802

def main():
    #追加
    session = requests.Session()

    options = ChromeOptions()
    driver = Chrome(options=options) 



    actions = ActionChains(driver)

    url = navigate(driver, actions, session)
    
  
    response = session.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    contents = scrape_content_for_login(soup)
    write_to_csv(contents)



def navigate(driver, actions, session):

    ---#省略---


    WebDriverWait(driver, 30).until(EC.visibility_of_element_located)

    url = driver.current_url
    
    # 追加 Cookie情報をアップデート
    for cookie in driver.get_cookies():
        c = {cookie['name']: cookie['value']}
        session.cookies.update(c)
    session.headers.update(headers)

    return url

def scrape_content_for_login(soup):

    logging.info('scraping.....')
    contents = []
    for book in soup.select('#zg-ordered-list > li > span > div > span'):
        title = book.select_one('span > div > span > a > div.p13n-sc-truncate').get_text(strip=True)
        price = book.select_one('span.p13n-sc-price').get_text(strip=True)
        try:
            popular = book.select_one('div.a-icon-row.a-spacing-none > a.a-size-small.a-link-normal').get_text(strip=True)
        except:
            popular = '評価無し'

        contents.append({
            'title': title,
            'price': price,
            'popular':popular,
        })
    logging.info(f'scraped {len(contents)} data')
    return contents

0Like

Your answer might help someone💌