1, デバックしていませんがコードを見て原因はfor i in range(1,9):
だと思います。
一般名称.xlsx
の行を取得するためのindex
と
URL_DATA.xlsx
に出力するための行番号(index
)で使い回しを行っているからかと。
別の変数としてください。
行単位に出力するならば、listにtupleで格納するのも良いのでは。
2, 日付が各行に出力されない原因は以下のインデントが一段深いです。
Python
1 time . sleep ( 2 )
2 time_data = datetime . datetime . today ( )
3
4 ws [ 'A' + str ( i ) ] . value = time_data
追記・修正依頼欄に書ききれないので。
a. 初心者の方に多いのですが、質問者さんのように処理を一つの関数にどんどん追加していく人が多いです。
これをしてしまうとなんらかの問題がソースコードに発生したときに、
どこの処理が問題なのかの原因の切り分けが不可能になりやすいです。
今回の件は出力の問題なのでスクレイピングはほぼ 関係ないですよね。
でも同じ関数内に書いてしまうとほぼ なのでもしかしたら関係あるかもで調査する必要があります。
対策としては適度な関数分割です。
スクレイピングをして、HTMLを取得する部分のコードは以下のようにできます。
こうすることでスクレイピングの処理は関数内で閉じているので、該当の処理は意識しなくても良くなります。
Python
1 def get_content ( word ) :
2 """
3 スクレイピングする。
4 :param word 検索キーワード
5 :return スクレイピング結果(HTML)とURL
6 ※ chromedriver.exe をCドライブ直下に置くこと。
7 """
8 driver = webdriver . Chrome ( r'C:/chromedriver.exe' )
9 driver . get ( "https://www.pmda.go.jp/PmdaSearch/kikiSearch/" )
10 # id検索
11 elem_search_word = driver . find_element_by_id ( "txtName" )
12 elem_search_word . send_keys ( word )
13 # name検索
14 elem_search_btn = driver . find_element_by_name ( 'btnA' )
15 elem_search_btn . click ( )
16 change_window ( driver )
17
18 # print(driver.page_source)
19 html = driver . page_source
20 cur_url = driver . current_url
21 return html , cur_url
22
Python
1 html , cur_url = get_content ( word )
一般名称.xlsxから検索キーワードを取得する部分は以下のように(未テスト)
Python
1 def get_search_keyword ( ) :
2 """
3 エクセルファイルを開き、検索キーワードを取得する。
4 """
5 # テスト用
6 #yield "血液照射装置"
7 #yield "放射性医薬品合成設備"
8 from contextlib import closing
9 with closing ( op . load_workbook ( '一般名称.xlsx' ) ) as wb :
10 for i in range ( 1 , 9 ) :
11 ws = wb . active
12 yield ws [ 'A' + str ( i ) ] . value
Python
1 for i , word in enumerate ( get_search_keyword ( ) , start = 1 ) :
b, 次に一般名称.xlsx
やURL_DATA.xlsx
のファイルが回答者の環境には無いため実行再現しずらいです。
適当なサンプルデータを質問文に追記していただくか。
もしくはウィンドウズ環境にしかないxlsx
ではなく汎用性のあるデータ構造csv形式など。
この質問はリストに質問文の画像のような形で値を格納したい とも言いかえれます。
こちらなら環境を選ばないので回答が付きやすいかと。
◇不具合
2列目にFalse
が出力される原因はこのコードですね。
has_pdf_link
がBool
型で値がFalse
が設定されています。
Python
1 if not has_pdf_link :
2 print ( 'False' )
3 ws [ 'B' + str ( i ) ] . value = has_pdf_link
4
試しにselenium
とopenpyxl
を使わないように出力はリストになるように書き換えてみました。
Python
1 # -*- coding: utf-8 -*-
2 from bs4 import BeautifulSoup
3 from urllib . parse import urljoin
4 import datetime
5 import time
6 #import openpyxl as op
7
8
9 def get_content ( word : str ) :
10 return """
11 <table class="SearchResultTable" id="ResultList">
12 <tbody><tr>
13 <th scope="col" style="width:13em" nowrap="">一般的名称</th>
14 <th scope="col" style="width:15em" nowrap="">販売名</th>
15 <th scope="col" style="width:15em" nowrap="">製造販売業者等</th>
16 <th scope="col" style="width:13em" nowrap="">添付文書</th>
17 <th scope="col" style="width:13em" nowrap="">改訂指示<br />反映履歴</th>
18 <th scope="col" style="width:13em" nowrap="">審査報告書/<br />再審査報告書等</th>
19 <th scope="col" style="width:13em" nowrap="">緊急安全性情報</th>
20 </tr>
21 <tr class="TrColor01">
22 <td><div><a target="_blank" href="/PmdaSearch/kikiDetail/GeneralList/20500BZZ00241000_A_01">血液照射装置</a></div></td>
23 <td><div>日立X線照射装置 MBR−1520A−TW</div></td>
24 <td><div>製造販売/株式会社 日立メディコ</div></td>
25 <td><div><a href="javascript:void(0)" onclick="detailDisp("PmdaSearch" ,"650053_20500BZZ00241000_A_01_01");">HTML</a><br /><a target="_blank" href="/PmdaSearch/kikiDetail/ResultDataSetPDF/650053_20500BZZ00241000_A_01_01">PDF (2007年12月19日)</a></div></td>
26 <td></td>
27 <td></td>
28 <td></td>
29 </tr>
30 </tbody></table>
31 """ , "https://www.pmda.go.jp/PmdaSearch/kikiSearch/"
32
33
34 def get_search_keyword ( ) :
35 # テスト用
36 yield "血液照射装置"
37 yield "放射性医薬品合成設備"
38
39
40 def parse ( soup , cur_url : str ) :
41 """
42 スクレイピング結果を解析
43 """
44 for a_tag in soup . find_all ( 'a' ) :
45 link_pdf = ( urljoin ( cur_url , a_tag . get ( 'href' ) ) )
46 # link_PDFから文末がpdfと文中にPDFが入っているものを抽出
47 if ( not link_pdf . lower ( ) . endswith ( '.pdf' ) ) and ( '/ResultDataSetPDF/' not in link_pdf ) :
48 continue
49 if 'searchhelp' not in link_pdf :
50 yield True , link_pdf
51
52
53 def main ( ) :
54 for i , word in enumerate ( get_search_keyword ( ) , start = 1 ) :
55 html , cur_url = get_content ( word )
56 soup = BeautifulSoup ( html , 'html.parser' )
57 output = [ ]
58 time_data = datetime . datetime . today ( )
59 for has_pdf_link , link_pdf in parse ( soup , cur_url ) :
60 output . append ( [ time_data , link_pdf , word ] )
61 print ( link_pdf )
62
63 print ( output )
64
65
66 if __name__ == "__main__" :
67 main ( )
以下のFalse
の仕様がよく分かりませんでしたので、その部分がうまく実装できてないですが。
質問文の画像を見る限りこういうふうに出力したいのでしょうか。
Python
1 if not has_pdf_link :
2 print ( 'False' )
3 ws [ 'B' + str ( i ) ] . value = has_pdf_link
4
5 time . sleep ( 2 )
6 time_data = datetime . datetime . today ( )
7
8 ws [ 'A' + str ( i ) ] . value = time_data
Python
1 # -*- coding: utf-8 -*-
2 from selenium import webdriver
3 from selenium . webdriver . common . by import By
4 from selenium . webdriver . support . ui import WebDriverWait
5 from urllib import request
6 from bs4 import BeautifulSoup
7 import requests
8 from urllib . parse import urljoin
9 import openpyxl as op
10 import datetime
11 import time
12
13
14 def get_search_keyword ( ) :
15 """
16 エクセルファイルを開き、検索キーワードを取得する。
17 """
18 # テスト用
19 #yield "血液照射装置"
20 #yield "放射性医薬品合成設備"
21 from contextlib import closing
22 with closing ( op . load_workbook ( '一般名称.xlsx' ) ) as wb :
23 for i in range ( 1 , 9 ) :
24 ws = wb . active
25 yield ws [ 'A' + str ( i ) ] . value
26
27
28 def get_content ( word : str ) - > tuple :
29 """
30 スクレイピングする。
31 :param word 検索キーワード
32 :return スクレイピング結果(HTML)とURL
33 ※ chromedriver.exe をCドライブ直下に置くこと。
34 """
35 def change_window ( browser ) :
36 """
37 ブラウザのウィンドウを切り替える。
38 """
39 all_handles = set ( browser . window_handles )
40 switch_to = all_handles - set ( [ browser . current_window_handle ] )
41 assert len ( switch_to ) == 1
42 browser . switch_to . window ( * switch_to )
43
44 driver = webdriver . Chrome ( r'C:/chromedriver.exe' )
45 driver . get ( "https://www.pmda.go.jp/PmdaSearch/kikiSearch/" )
46 # id検索
47 elem_search_word = driver . find_element_by_id ( "txtName" )
48 elem_search_word . send_keys ( word )
49 # name検索
50 elem_search_btn = driver . find_element_by_name ( 'btnA' )
51 elem_search_btn . click ( )
52 change_window ( driver )
53
54 # print(driver.page_source)
55 html = driver . page_source
56 cur_url = driver . current_url
57 driver . quit ( )
58
59 return html , cur_url
60
61
62 def parse ( soup , cur_url : str ) :
63 """
64 スクレイピング結果を解析
65 """
66 for a_tag in soup . find_all ( 'a' ) :
67 link_pdf = ( urljoin ( cur_url , a_tag . get ( 'href' ) ) )
68 #print(link_pdf)
69 # link_PDFから文末がpdfと文中にPDFが入っているものを抽出
70 if ( not link_pdf . lower ( ) . endswith ( '.pdf' ) ) and ( '/ResultDataSetPDF/' not in link_pdf ) :
71 continue
72 if 'searchhelp' not in link_pdf :
73 yield True , link_pdf
74
75
76 def output_excel ( output : list , row_index : int ) :
77 """
78 エクセルに出力する。
79 :param output 行データ
80 :param row_index 出力するための開始行
81 """
82 #wb = op.load_workbook('URL_DATA.xlsx')
83 #ws = wb.active
84 print ( "#" * 50 )
85 for i , ( time_data , link_pdf , word_col ) in enumerate ( output , start = row_index ) :
86 print ( i , time_data , link_pdf , word_col )
87 # ここにエクセルの設定処理を
88
89 #wb.save('URL_DATA.xlsx')
90
91
92 def main ( ) :
93 START_ROW = 0
94 row_index = 1
95 for word in get_search_keyword ( ) :
96 html , cur_url = get_content ( word )
97 soup = BeautifulSoup ( html , 'html.parser' )
98 output = [ ]
99 time_data = datetime . datetime . today ( )
100 for i , ( has_pdf_link , link_pdf ) in enumerate ( parse ( soup , cur_url ) , start = START_ROW ) :
101 word_col = word if i == START_ROW else ""
102 output . append ( [ time_data , link_pdf , word_col ] )
103
104 output_excel ( output , row_index )
105 row_index += len ( output )
106
107
108 if __name__ == "__main__" :
109 main ( )
110
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/07/23 09:20
2018/07/23 09:41 編集
2018/07/23 10:03
2018/07/23 10:06
2018/07/23 10:43
2018/07/23 10:45
2018/07/23 10:53
2018/07/23 11:00
2018/07/23 12:56
2018/07/23 13:09
2018/07/23 16:10
2018/07/23 17:07 編集
2018/07/24 01:46