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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Q&A

3回答

952閲覧

PythonによるDOMの取得

jerald

総合スコア6

Python 3.x

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

0グッド

0クリップ

投稿2018/05/15 07:23

前提・実現したいこと

PythonでサイトのDOMを取得するプログラムを作成中です。
対象
"http://www2.keiba.go.jp/KeibaWeb/TodayRaceInfo/RaceMarkTable?k_raceDate=2012%2f01%2f01&k_raceNo=11&k_babaCode=21"

元にしたもの
https://qiita.com/suecharo/items/cc2b0758bf549f0dbb29
これをもとに上記対象のサイトを読むようにしたのですが、エラーがでます。

発生している問題・エラーメッセージ

Traceback (most recent call last): File "C:\app\py\keiba.py", line 120, in <module> main() File "C:\app\py\keiba.py", line 83, in main seiseki() File "C:\app\py\keiba.py", line 93, in seiseki tuple_get_text = seisekicrawling(dom) File "C:\app\py\keiba.py", line 74, in seisekicrawling get_text = make_text_from_xpath(dom, '//*[@id="container00"]/table/tbody/tr[2]/td/table/tbody/tr/td/table[4]/tbody/tr/td/table/tbody/tr[' + str(tr num) + ']/td[2]/text()') File "C:\app\py\keiba.py", line 44, in make_text_from_xpath text = dom.xpath(xpath)[0].text IndexError: list index out of range

該当のソースコード

Pythonソースコード

1# coding: utf-8 2import requests # urlにGETリクエストしてhtmlを取得 3from fake_useragent import UserAgent # headerを生成 4import lxml.html # xmlパーサ 5import time # 遅延生成用 6 7 8def make_scraping_url(page_num): 9 scraping_url = "http://www2.keiba.go.jp/KeibaWeb/TodayRaceInfo/RaceMarkTable?k_raceDate=2012%2f01%2f01&k_raceNo=11&k_babaCode=21" 10 return scraping_url 11 12 13counter_200 = 0 14counter_404 = 0 15 16 17def make_html_text(scraping_url): 18 global counter_200 19 global counter_404 20 21 ua = UserAgent() # fakeuser-agentのオブジェクト 22 ran_header = {"User-Agent": ua.random} # 呼び出されるたびにランダムなheaderを生成 23 html = requests.get(scraping_url, headers=ran_header) # requestsにより得られたhtmlのオブジェクト 24 html_text = html.text 25 26 if html.status_code == 200: 27 counter_200 += 1 28 elif html.status_code == 400: 29 counter_404 += 1 30 31 return html_text 32 33 34# Document Object Model、htmlをxml形式に変換して生成される 35def make_dom(html_text): 36 dom = lxml.html.fromstring(html_text) 37 return dom 38 39 40# domとxpathを受け取ってtextを返す 41def make_text_from_xpath(dom, xpath): 42 43 try: 44 text = dom.xpath(xpath)[0].text 45 except AttributeError: 46 text = str(dom.xpath(xpath)[0]) 47 48 return text 49 50 51# domとxpathを受け取ってlinkを返す 52def make_link_from_xpath(dom, xpath): 53 link = dom.xpath(xpath)[0].attrib["href"] 54 return link 55 56 57# 取得したいテキストがtext()に内包されている場合 58def make_text_from_xpath_function(dom, xpath): 59 text = dom.xpath(xpath)[1] 60 return text 61 62 63# scrapingしたい情報の項目とそのxpathをまとめたクラス、最初に個別記事が上から何番目かを渡す 64class Xpath: 65 def __init__(self, article_num): 66 self.article_num = article_num 67 self.info_list = [] 68 69def seisekicrawling(dom): 70 list_get_text = [] # 1記事分の情報をまとめるためのlist、MySQLへのinsertにはtuple型を使うため、後ほど変換する 71 trnum = 3 72 73 while trnum <= 15: 74 get_text = make_text_from_xpath(dom, '//*[@id="container00"]/table/tbody/tr[2]/td/table/tbody/tr/td/table[4]/tbody/tr/td/table/tbody/tr[' + str(trnum) + ']/td[2]/text()') 75 list_get_text.append(get_text) 76 trnum = trnum + 1 77 return list_get_text 78 79 80def main(): 81 global counter_200 82 83 seiseki() 84 85def seiseki(): 86 # アクセス 87 scraping_url = 'http://www2.keiba.go.jp/KeibaWeb/TodayRaceInfo/RaceMarkTable?k_raceDate=2012%2f01%2f01&k_raceNo=11&k_babaCode=21' 88 html_text = make_html_text(scraping_url) 89 tfile = open('html_text.html', 'wt')# 90 tfile.write(html_text)# 91 tfile.close()# 92 dom = make_dom(html_text) 93 tuple_get_text = seisekicrawling(dom) 94 95 96def debug_check_where_link_number(page_num, article_num): 97 scraping_url = make_scraping_url(page_num) 98 html_text = make_html_text(scraping_url) 99 dom = make_dom(html_text) 100 xpath = Xpath(article_num) 101 102 thumbnail_link = check_thumbnail_link(dom, article_num) 103 if thumbnail_link[0] is True and thumbnail_link[1] is True: 104 xpath.with_thumbnail() 105 elif thumbnail_link[0] is False: 106 xpath.no_thumbnail() 107 elif thumbnail_link[1] is False: 108 xpath.deleted() 109 110 get_link = make_link_from_xpath(dom, xpath.info_list[1]) 111 l_get_link = get_link.split("/") 112 counter = 0 113 for item in l_get_link: 114 print(counter) 115 counter += 1 116 print(item) 117 118 119if __name__ == "__main__": 120 main()

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

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

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

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

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

guest

回答3

0

IndexError: list index out of range

エラーメッセージを読みましょう

投稿2018/05/15 07:35

y_waiwai

総合スコア87774

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

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

0

dom.xpath(xpath) の結果が、配列ではない。
そのため、dom.xpath(xpath)[0]で「list index out of range」エラーが発生した。

という事だと思われます。

dom.xpath(xpath)で、どんな値が返されるのかを確認することからデバッグに着手しては如何でしょうか。

投稿2018/05/15 08:32

coco_bauer

総合スコア6915

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

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

jerald

2018/05/16 05:43

42行目に print(dom.xpath(xpath)) で[]が表示されます。取得されていません。 print(xpath)は //*[@id="container00"]/table/tbody/tr[2]/td/table/tbody/tr/td/table[4]/tbody/tr/td/table/tbody/tr[3]/td[2]/text()
coco_bauer

2018/05/16 06:42

実際のDOMオブジェクトの構造と、xpathの指定が合っていないのでしょうね。取得したDOMオブジェクトの構造を確認されましたか?
guest

0

dom.xpath(xpath)で空リストが返っています。取得がうまくいっていないのでしょう。
サイトがちゃんと取れていることと、xpathの正しさを確認してください。

追記

chromeが勝手にtbodyタグを挿入しているため、取得したxpathと本来のデータが一致しないためです。

python

1xpath = '//div[@id="container00"]/table/tr[2]/td/table/tr/td/table[4]/tr/td/table/tr[3]/td[2]'

これで動きました
参考
スクレイピングにChromeのディベロッパーツールが便利 | あっかぎのページ

投稿2018/05/15 07:49

編集2018/05/17 13:38
hayataka2049

総合スコア30933

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

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

jerald

2018/05/16 06:03

90-92行目で作成されるhtml_text.htmlは正常に取得されています 42行目にprint(xpath)を入れると //*[@id="container00"]/table/tbody/tr[2]/td/table/tbody/tr/td/table[4]/tbody/tr/td/table/tbody/tr[3]/td[2]/text()
hayataka2049

2018/05/16 07:04

あー、わかりました。chromeの検証でやったらtbodyがあるんだけど、オリジナルのソースではぜんぶ省略されています。chromeが勝手に挿入してるだけで xpath = '//div[@id="container00"]/table/tr[2]/td/table/tr/td/table[4]/tr/td/table/tr[3]/td[2]' これで動きました 参考 http://akkagi.info/20150228_web/
hayataka2049

2018/05/17 13:39

質問にも追記しました。気づいて・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問