前提
競馬のデータをスクレイピングで収集したいと思い、勉強している最中です。
全くの無学ですが、Pythonを用い、Pandasの「read_html」を使ってnetkeibaのレースのデータのtableを取得することに成功しました。が、次に同じ要領でJRAの騎手の騎乗予定ページからtableを取得しようとするとHTTPエラーが出ていまいました。
考えうる理由としては
・そのページにそもそもtableが存在しない
・HP側がスクレイピングを禁止している
・URLが適切ではない
等が浮かびましたが、理由が浮かんでも解決方法が浮かびません。
未熟者ではありますが、先達のご指導ご鞭撻の程をよろしくお願いします。
実現したいこと
https://www.jra.go.jp/JRADB/accessK.html
・上記のHPの騎乗予定のtableを「read_html」を用いて取得するにあたって、エラーが出る理由を知りたい。
・その上でその解決方法を知りたい。
発生している問題・エラーメッセージ
--------------------------------------------------------------------------- HTTPError Traceback (most recent call last) Input In [69], in <cell line: 4>() 2 #pandasのインポート 3 URL = 'https://www.jra.go.jp/JRADB/accessK.html' ----> 4 pd.read_html(URL) File ~\anaconda3\lib\site-packages\pandas\util\_decorators.py:311, in deprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper(*args, **kwargs) 305 if len(args) > num_allow_args: 306 warnings.warn( 307 msg.format(arguments=arguments), 308 FutureWarning, 309 stacklevel=stacklevel, 310 ) --> 311 return func(*args, **kwargs) File ~\anaconda3\lib\site-packages\pandas\io\html.py:1113, in read_html(io, match, flavor, header, index_col, skiprows, attrs, parse_dates, thousands, encoding, decimal, converters, na_values, keep_default_na, displayed_only) 1109 validate_header_arg(header) 1111 io = stringify_path(io) -> 1113 return _parse( 1114 flavor=flavor, 1115 io=io, 1116 match=match, 1117 header=header, 1118 index_col=index_col, 1119 skiprows=skiprows, 1120 parse_dates=parse_dates, 1121 thousands=thousands, 1122 attrs=attrs, 1123 encoding=encoding, 1124 decimal=decimal, 1125 converters=converters, 1126 na_values=na_values, 1127 keep_default_na=keep_default_na, 1128 displayed_only=displayed_only, 1129 ) File ~\anaconda3\lib\site-packages\pandas\io\html.py:919, in _parse(flavor, io, match, attrs, encoding, displayed_only, **kwargs) 916 p = parser(io, compiled_match, attrs, encoding, displayed_only) 918 try: --> 919 tables = p.parse_tables() 920 except ValueError as caught: 921 # if `io` is an io-like object, check if it's seekable 922 # and try to rewind it before trying the next parser 923 if hasattr(io, "seekable") and io.seekable(): File ~\anaconda3\lib\site-packages\pandas\io\html.py:239, in _HtmlFrameParser.parse_tables(self) 231 def parse_tables(self): 232 """ 233 Parse and return all tables from the DOM. 234 (...) 237 list of parsed (header, body, footer) tuples from tables. 238 """ --> 239 tables = self._parse_tables(self._build_doc(), self.match, self.attrs) 240 return (self._parse_thead_tbody_tfoot(table) for table in tables) File ~\anaconda3\lib\site-packages\pandas\io\html.py:758, in _LxmlFrameParser._build_doc(self) 756 pass 757 else: --> 758 raise e 759 else: 760 if not hasattr(r, "text_content"): File ~\anaconda3\lib\site-packages\pandas\io\html.py:739, in _LxmlFrameParser._build_doc(self) 737 try: 738 if is_url(self.io): --> 739 with urlopen(self.io) as f: 740 r = parse(f, parser=parser) 741 else: 742 # try to parse the input in the simplest way File ~\anaconda3\lib\site-packages\pandas\io\common.py:239, in urlopen(*args, **kwargs) 233 """ 234 Lazy-import wrapper for stdlib urlopen, as that imports a big chunk of 235 the stdlib. 236 """ 237 import urllib.request --> 239 return urllib.request.urlopen(*args, **kwargs) File ~\anaconda3\lib\urllib\request.py:214, in urlopen(url, data, timeout, cafile, capath, cadefault, context) 212 else: 213 opener = _opener --> 214 return opener.open(url, data, timeout) File ~\anaconda3\lib\urllib\request.py:523, in OpenerDirector.open(self, fullurl, data, timeout) 521 for processor in self.process_response.get(protocol, []): 522 meth = getattr(processor, meth_name) --> 523 response = meth(req, response) 525 return response File ~\anaconda3\lib\urllib\request.py:632, in HTTPErrorProcessor.http_response(self, request, response) 629 # According to RFC 2616, "2xx" code indicates that the client's 630 # request was successfully received, understood, and accepted. 631 if not (200 <= code < 300): --> 632 response = self.parent.error( 633 'http', request, response, code, msg, hdrs) 635 return response File ~\anaconda3\lib\urllib\request.py:561, in OpenerDirector.error(self, proto, *args) 559 if http_err: 560 args = (dict, 'default', 'http_error_default') + orig_args --> 561 return self._call_chain(*args) File ~\anaconda3\lib\urllib\request.py:494, in OpenerDirector._call_chain(self, chain, kind, meth_name, *args) 492 for handler in handlers: 493 func = getattr(handler, meth_name) --> 494 result = func(*args) 495 if result is not None: 496 return result File ~\anaconda3\lib\urllib\request.py:641, in HTTPDefaultErrorHandler.http_error_default(self, req, fp, code, msg, hdrs) 640 def http_error_default(self, req, fp, code, msg, hdrs): --> 641 raise HTTPError(req.full_url, code, msg, hdrs, fp) HTTPError: HTTP Error 403: Forbidden
該当のソースコード
!pip install lxml html5lib beautifulsoup4 !pip install pandas import pandas as pd URL = 'https://www.jra.go.jp/JRADB/accessK.html' pd.read_html(URL)
試したこと
別のHPに記載されている騎乗予定のページも試したが、同じエラーが出てしまった。
・https://www.keibalab.jp/db/jockey/01019/
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
回答2件
あなたの回答
tips
プレビュー