質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

2回答

15302閲覧

python スクレイピング エラーコード(ValueError: Length of values does not match length of index)を解決したい

Kantan.lab

総合スコア22

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2020/04/07 02:56

#目的
ValueError: Length of values does not match length of index のエラーを解決したい。

背景

とある求人サイトをスクレイピングし、pandasをつかってCSVファイルに格納する過程で、取得項目が不規則でCSV格納するとlengthが合わなくなりエラーになる。

該当コード

from selenium import webdriver from time import sleep import pandas as pd import re browser = webdriver.Chrome() browser.get('https://re-katsu.jp/career/search/kanto/') st_urls = [] for page in range( 1,36): url = 'https://re-katsu.jp/career/search/kanto/?pagCnt={}'.format(page) browser.get(url) sleep(1) browser.find_element_by_css_selector details = browser.find_elements_by_class_name('headers') for detail in details: _url = detail.find_element_by_tag_name("h3 a") _url = _url.get_attribute("href") list_urls.append(_url) industry_mix = [] up_mix = [] c_mix = [] occ_mix = [] f_salary_mix = [] area_mix = [] staff_mix = [] c_address_mix = [] hp_mix = [] info_mix = [] for url in list_urls: url = browser.get(url) sleep(1) #会社名 c_names = browser.find_element_by_class_name("headers").find_elements_by_tag_name("h2") for c_name in c_names: _mix = c_name.text c_mix.append(_mix) #掲載終了予定日 updates = browser.find_element_by_class_name("article-data").find_elements_by_id('ctl00_ContentPlaceHolder1_lblPublishedLastdate') for update in updates: _mix = update.text up_mix.append(_mix) #業種 industrys = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblIndustryIcon') for industry in industrys: _mix = industry.text industry_mix.append(_mix) #職種 occs = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblServIcon') for occ in occs: _mix = occ.text occ_mix.append(_mix) #初年度給与 f_salarys = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblIncomeIcon') for f_salary in f_salarys: _mix = f_salary.text f_salary_mix.append(_mix) #勤務地 areas = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblWorkLocateIcon') for area in areas: _mix = area.text area_mix.append(_mix) #従業員数 staffs = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_trEmployeesCount') if not len(staffs) == len(c_names): for staff in staffs: _mix = staff.text staff_mix.append(_mix) #本社所在地 c_addresses = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblHeadofficelocation') for c_address in c_addresses: _mix = c_address.text c_address_mix.append(_mix) #HP hps = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblLink_Body1') for hp in hps: _mix = hp.text hp_mix.append(_mix) #連絡先 pattern = r'[(]{0,1}[0-9]{2,4}[)\-(]{0,1}[0-9]{2,4}[)\-]{0,1}[0-9]{3,4}' infos = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblContactInfo') for info in infos: _mix = info.text #regex = re.compile(pattern, flags=0) #mo = regex.search(_mix) #mo.group() info_mix.append(_mix) df = pd.DataFrame() df['会社名'] = c_mix df['掲載終了予定日'] = up_mix df['業種'] = industry_mix df['職種'] = occ_mix df['初年度年収'] = f_salary_mix df['勤務地'] = area_mix df['従業員数'] = staff_mix df['本社所在地'] = c_address_mix df['HP'] = hp_mix df['連絡先'] = info_mix

エラーコード

ValueError Traceback (most recent call last) <ipython-input-363-7e5d40ae8e25> in <module> 5 df['初年度年収'] = f_salary_mix 6 df['勤務地'] = area_mix ----> 7 df['従業員数'] = staff_mix 8 df['本社所在地'] = c_address_mix 9 df['HP'] = hp_mix ~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/frame.py in __setitem__(self, key, value) 3470 else: 3471 # set column -> 3472 self._set_item(key, value) 3473 3474 def _setitem_slice(self, key, value): ~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/frame.py in _set_item(self, key, value) 3547 3548 self._ensure_valid_index(value) -> 3549 value = self._sanitize_column(key, value) 3550 NDFrame._set_item(self, key, value) 3551 ~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/frame.py in _sanitize_column(self, key, value, broadcast) 3732 3733 # turn me into an ndarray -> 3734 value = sanitize_index(value, self.index, copy=False) 3735 if not isinstance(value, (np.ndarray, Index)): 3736 if isinstance(value, list) and len(value) > 0: ~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/internals/construction.py in sanitize_index(data, index, copy) 610 611 if len(data) != len(index): --> 612 raise ValueError("Length of values does not match length of index") 613 614 if isinstance(data, ABCIndexClass) and not copy: ValueError: Length of values does not match length of index

初心者のため、ご教示お願いいたします!!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

python

1from selenium import webdriver 2from time import sleep 3import pandas as pd 4import re 5browser = webdriver.Chrome() 6browser.get('https://re-katsu.jp/career/search/kanto/') 7 8st_urls = [] 9 10page_num = 36 11 12list_urls = [[""]] * page_num 13 14for page in range( 1,page_num): 15 url = 'https://re-katsu.jp/career/search/kanto/?pagCnt={}'.format(page) 16 browser.get(url) 17 18 sleep(1) 19 browser.find_element_by_css_selector 20 details = browser.find_elements_by_class_name('headers') 21 for detail in details: 22 _url = detail.find_element_by_tag_name("h3 a") 23 _url = _url.get_attribute("href") 24 list_urls[page] = _url 25 26urls_num = len(list_urls) 27 28empty_list = [[""] * urls_num for i in range(10)] 29industry_mix, up_mix,c_mix,occ_mix,f_salary_mix, area_mix,staff_mix,c_address_mix, hp_mix,info_mix = empty_list 30 31 32for n, url in enumerate(list_urls): 33 if url == [""]: 34 continue 35 36 url = browser.get(url) 37 sleep(1) 38 39 #会社名 40 c_names = browser.find_element_by_class_name("headers").find_elements_by_tag_name("h2") 41 for c_name in c_names: 42 _mix = c_name.text 43 c_mix[n] = _mix 44 45 #掲載終了予定日 46 updates = browser.find_element_by_class_name("article-data").find_elements_by_id('ctl00_ContentPlaceHolder1_lblPublishedLastdate') 47 for update in updates: 48 _mix = update.text 49 up_mix[n] = _mix 50 51 #業種 52 industrys = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblIndustryIcon') 53 for industry in industrys: 54 _mix = industry.text 55 industry_mix[n] = _mix 56 57 #職種 58 occs = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblServIcon') 59 for occ in occs: 60 _mix = occ.text 61 occ_mix[n] = _mix 62 63 #初年度給与 64 f_salarys = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblIncomeIcon') 65 for f_salary in f_salarys: 66 _mix = f_salary.text 67 f_salary_mix[n] = _mix 68 69 #勤務地 70 areas = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblWorkLocateIcon') 71 for area in areas: 72 _mix = area.text 73 area_mix[n] = _mix 74 75 76 #従業員数 77 staffs = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_trEmployeesCount') 78 if not len(staffs) == len(c_names): 79 for staff in staffs: 80 _mix = staff.text 81 staff_mix[n] = _mix 82 83 #本社所在地 84 c_addresses = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblHeadofficelocation') 85 for c_address in c_addresses: 86 _mix = c_address.text 87 c_address_mix[n] = (_mix) 88 89 #HP 90 hps = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblLink_Body1') 91 for hp in hps: 92 _mix = hp.text 93 hp_mix[n] = (_mix) 94 95 #連絡先 96 pattern = r'[(]{0,1}[0-9]{2,4}[)\-(]{0,1}[0-9]{2,4}[)\-]{0,1}[0-9]{3,4}' 97 infos = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_lblContactInfo') 98 for info in infos: 99 _mix = info.text 100 #regex = re.compile(pattern, flags=0) 101 #mo = regex.search(_mix) 102 #mo.group() 103 info_mix[n] = (_mix) 104 105df = pd.DataFrame() 106 107df['会社名'] = c_mix 108df['掲載終了予定日'] = up_mix 109df['業種'] = industry_mix 110df['職種'] = occ_mix 111df['初年度年収'] = f_salary_mix 112df['勤務地'] = area_mix 113df['従業員数'] = staff_mix 114df['本社所在地'] = c_address_mix 115df['HP'] = hp_mix 116df['連絡先'] = info_mix 117 118df = df.drop([0])

これで10行目にある
page_numの値を変えれば
その分取得できると思います

投稿2020/04/17 00:26

編集2020/04/17 03:32
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kantan.lab

2020/04/17 02:02

おぉ!ありがとうございます! 実行してみました! しかし、レコードが取得出来ているものと出来ていないものがあります。。。。
退会済みユーザー

退会済みユーザー

2020/04/17 03:22

取得できていないところはHPのところですか?
退会済みユーザー

退会済みユーザー

2020/04/17 03:27

あとidはおなじのが複数個あることはないので find_elementsをfind_elementに変えてfor文を消すこともできると思います
guest

0

「従業員数」がサイトにない場合は、代わりの値を追加すれば良いでしょう。(例えば"-")


【追記】下記の様な感じでしょうか?

Python

1#従業員数 2staffs = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_trEmployeesCount') 3if len(staffs) == 0: 4 staff_mix.append('-')

ただ質問のコードでfind_elements_by_idと複数の要素を取得しようとしていますが、サイトに複数の要素が存在するのでしょうか?(下記コードはインデントがおかしいのでよく分かりませんが)

#従業員数 staffs = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_trEmployeesCount') if not len(staffs) == len(c_names): for staff in staffs: _mix = staff.text staff_mix.append(_mix)

URLによって要素数の変化がある場合はURL毎にデータの管理が必要になるかと思います。その場合はリストよりも辞書でデータを管理した方が良いかもしれません。
※実際にコードを動かして検証はしていません。

投稿2020/04/07 12:21

編集2020/04/08 11:44
meg_

総合スコア10577

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kantan.lab

2020/04/07 12:57

ありがとうございます! そのような場合はif 文をつかいますよね? ただ、申し訳ないのですが、どのようなメソッドが必要になるかごきょうじいただけますか?
Kantan.lab

2020/04/09 12:22

ありがとうございます! 辞書データとはkey value での管理ですよね? 一旦以下のような条件式を組んだのですが..なぜかエラーは出ないのですが途中で処理が止まってしまいます。 #従業員数 staffs = browser.find_elements_by_id('ctl00_ContentPlaceHolder1_trEmployeesCount') while len(c_names) != len(staffs): staff_mix.append("-") if len(c_names) == len(staffs): break for staff in staffs: _mix = staff.text staff_mix.append(_mix)
meg_

2020/04/09 12:47

上記コードではインデントは判別できないのでよく分かりませんが、無限ループしていませんか?
Kantan.lab

2020/04/09 13:48

はい、してますねw
Kantan.lab

2020/04/09 13:50

もしよろしければですが、時給1500円で直接レビューお願いできませんか?
meg_

2020/04/09 14:22

業務は受け付けておりませんw
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問