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

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

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

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

Q&A

解決済

1回答

1853閲覧

エンコードに関するエラーについて

S.katou

総合スコア1

Python 3.x

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

0グッド

0クリップ

投稿2022/01/21 12:42

編集2022/01/22 03:06

pythonでguiを用いてスクレイピングツールを作っています

どうか助言をいただければ幸いです。
よろしくお願いいたします。

下のコードでスクレイピングすることは可能でしたが、3点問題がありまして
1.UnicodeEncodeError: 'latin-1' codec can't encode characters in position 8-13: ordinal not in range(256)という、エンコードに関するエラーが出てしまう
2.カウント機能が機能しておらず、記事数指定が出来ない及び、それらはVS Codeのデバッグ機能をすり抜けてしまう
3.VS Codeのpython上ではエラーが起きないが、パワーシェル(ターミナル)上で実行すると更に下のエラー文が出てきてしまう
という状況です。下図の通り、カウントが機能しないので送信上限の1000文字分だけ送っています。

イメージ説明
カウント機能を実装する時に出た以下エラーを無茶苦茶なint変換などで通したのが原因なのでしょうか?

python

1 if count > stop_count: 2TypeError: '>' not supported between instances of 'int' and 'str'

実際のコードです

python

1#!/usr/bin/env python3 2# -*- coding: UTF-8 -*- 3# 4# generated by wxGlade 1.1.0pre on Thu Jan 13 14:50:45 2022 5# 6 7import wx 8from bs4 import BeautifulSoup 9import requests 10import datetime 11 12# begin wxGlade: dependencies 13# end wxGlade 14 15# begin wxGlade: extracode 16# end wxGlade 17 18 19 20class Myframe(wx.Frame): 21 def __init__(self, *args, **kwds): 22 # begin wxGlade: Myframe.__init__ 23 kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE 24 wx.Frame.__init__(self, *args, **kwds) 25 self.SetSize((800, 600)) 26 self.SetTitle("記事スクレイピング") 27 28 grid_sizer_1 = wx.GridSizer(4, 3, 0, 0) 29 30 label_4 = wx.StaticText(self, wx.ID_ANY, "取得したいジャンル:") 31 label_4.SetFont(wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) 32 grid_sizer_1.Add(label_4, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) 33 34 #コンボボックスの中身リストを作り、内部データとしてURLを埋め込む 35 self.combo_box_3 = wx.ComboBox(self, wx.ID_ANY,"", style=wx.CB_DROPDOWN | wx.CB_READONLY) 36 self.combo_box_3.Append("主要", 'https://news.yahoo.co.jp/topics/top-picks') 37 self.combo_box_3.Append("国内", 'https://news.yahoo.co.jp/topics/domestic') 38 self.combo_box_3.Append("国際", 'https://news.yahoo.co.jp/topics/world') 39 self.combo_box_3.Append("経済", 'https://news.yahoo.co.jp/topics/business') 40 self.combo_box_3.Append("エンタメ", 'https://news.yahoo.co.jp/topics/entertainment') 41 self.combo_box_3.Append("スポーツ", 'https://news.yahoo.co.jp/topics/sports') 42 self.combo_box_3.Append("IT", 'https://news.yahoo.co.jp/topics/it') 43 self.combo_box_3.Append("科学", 'https://news.yahoo.co.jp/topics/science') 44 self.combo_box_3.Append("ライフ", 'https://news.yahoo.co.jp/topics/life') 45 self.combo_box_3.Append("地域", 'https://news.yahoo.co.jp/topics/local') 46 47 self.combo_box_3.SetMinSize((200, 23)) 48 self.combo_box_3.SetFont(wx.Font(9, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "Yu Gothic UI")) 49 grid_sizer_1.Add(self.combo_box_3, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) 50 51 grid_sizer_1.Add((20, 20), 2, wx.ALIGN_CENTER | wx.ALL, 5) 52 53 label_5 = wx.StaticText(self, wx.ID_ANY, "一度に取得したい記事数:") 54 label_5.SetFont(wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, "")) 55 grid_sizer_1.Add(label_5, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) 56 57 self.combo_box_4 = wx.ComboBox(self, wx.ID_ANY, "", style=wx.CB_DROPDOWN | wx.CB_READONLY) 58 #str型を変換する方法が分からなかったので、愚直に内部データからかえてます 59 self.combo_box_4.Append("1",1) 60 self.combo_box_4.Append("2",2) 61 self.combo_box_4.Append("3",3) 62 self.combo_box_4.Append("4",4) 63 self.combo_box_4.Append("5",5) 64 self.combo_box_4.Append("6",6) 65 self.combo_box_4.Append("7",7) 66 self.combo_box_4.Append("8",8) 67 self.combo_box_4.Append("9",9) 68 self.combo_box_4.Append("10",10) 69 self.combo_box_4.Append("11",11) 70 self.combo_box_4.Append("12",12) 71 self.combo_box_4.Append("13",13) 72 self.combo_box_4.Append("14",14) 73 self.combo_box_4.Append("15",15) 74 self.combo_box_4.Append("16",16) 75 self.combo_box_4.Append("17",17) 76 self.combo_box_4.Append("18",18) 77 self.combo_box_4.Append("19",19) 78 self.combo_box_4.Append("20",20) 79 self.combo_box_4.Append("21",21) 80 self.combo_box_4.Append("22",22) 81 self.combo_box_4.Append("23",23) 82 self.combo_box_4.Append("24",24) 83 self.combo_box_4.Append("25",25) 84 85 86 87 self.combo_box_4.SetMinSize((200, 23)) 88 grid_sizer_1.Add(self.combo_box_4, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.ALL, 5) 89 90 grid_sizer_1.Add((20, 20), 2, wx.ALIGN_CENTER | wx.ALL, 5) 91 92 grid_sizer_1.Add((20, 20), 2, wx.ALIGN_CENTER | wx.ALL, 5) 93 94 95 self.button_5 = wx.Button(self, wx.ID_ANY, "実行") 96 grid_sizer_1.Add(self.button_5, 2, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT, 5) 97 98 self.button_6 = wx.Button(self, wx.ID_ANY, "キャンセル") 99 grid_sizer_1.Add(self.button_6, 2, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5) 100 101 self.SetSizer(grid_sizer_1) 102 103 self.Layout() 104 105 self.Bind(wx.EVT_BUTTON, self.OnExec, self.button_5) 106 self.Bind(wx.EVT_BUTTON, self.OnCancel, self.button_6) 107 # end wxGlade 108 109 def OnExec(self, event): # wxGlade: MyFrame.<event_handler> 110 global news,news2,news3,count 111 112 try: 113 114 url = self.combo_box_3.GetClientData(self.combo_box_3.GetSelection()) 115 soup = BeautifulSoup(requests.get(url).text, 'lxml') 116 117 d_today = datetime.date.today() 118 news = "↓↓↓ 本日" + str(d_today) + "のニュース↓↓↓" + '\r\n' 119 news2 = "ニュースの続き"'\r\n' 120 121 122 # URL取得 123 news_urls = [] 124 for li_tag in soup.find_all('li', {'class', 'newsFeed_item'}): 125 try: 126 news_urls.append(li_tag.find( 127 'a', {'class', 'newsFeed_item_link'})['href']) 128 except: 129 # 広告を読み飛ばす 130 pass 131 132 # 記事の題目と記事の発表日時 133 news_title = [] 134 news_date = [] 135 div_tags = soup.find_all('div', {'class', 'newsFeed_item_title'}) 136 for div_tag in div_tags: 137 news_title.append(div_tag.text) 138 news_date.append(div_tag.next_sibling.find('time').text) 139 140 #記事の取得数をカウントさせ、希望数に達した時点でブレイクする 141 #1000文字の送信上限を考慮し、13記事まで取得した時点で次のメッセージで送信するようにしている 142 count = 0 143 144 stop_count = 0 145 stop_count = self.combo_box_4.GetClientData(self.combo_box_4.GetSelection()) 146 147 for title ,date ,url in zip(news_title, news_date, news_urls): 148 149 if int(count) > int(stop_count): 150 break 151 elif count <= 13: 152 news += '{} ({}) {}'.format(title, date, url) + '\r\n' 153 else: 154 news2 += '{} ({}) {}'.format(title, date, url) + '\r\n' 155 156 count += 1 157 158 def send_line_notify(notification_message): 159 #LINEに通知する 160 line_notify_token = '(トークン名)yoBa589TcZI4cV' 161 line_notify_api = 'https://notify-api.line.me/api/notify' 162 headers = {'Authorization': f'Bearer {line_notify_token}'} 163 data = {'message': f'message: {notification_message}'} 164 requests.post(line_notify_api, headers = headers, data = data) 165 166 def main(): 167 #print(matome) 168 send_line_notify(news) 169 send_line_notify(news2) 170 if __name__ == "__main__": 171 main() 172 173 except Exception as e: 174 import traceback 175 print(traceback.format_exc()) 176 dlg = wx.MessageDialog(self, 'エラーが発生しました。入力内容を確認してください。', 177 'エラー', 178 wx.OK | wx.ICON_ERROR 179 ) 180 dlg.ShowModal() 181 dlg.Destroy() 182 else: 183 dlg = wx.MessageDialog(self, 'スクレイピング完了しました', 184 '完了', 185 wx.OK | wx.ICON_INFORMATION 186 ) 187 dlg.ShowModal() 188 dlg.Destroy() 189 190 def OnCancel(self, event): # wxGlade: Myframe.<event_handler> 191 self.Destroy() 192 193# end of class Myframe 194 195class MyApp(wx.App): 196 def OnInit(self): 197 self.frame = Myframe(None, wx.ID_ANY, "") 198 self.SetTopWindow(self.frame) 199 self.frame.Show() 200 return True 201 202# end of class MyApp 203 204if __name__ == "__main__": 205 app = MyApp(0) 206 app.MainLoop()

実行しましたところ、以下のエラー文が出てきました。
長大なエラー文ですが、エンコードに関するメッセージです。※同じ部分は省かせて頂きました。

python

1Traceback (most recent call last): 2 File "C:\Users\ユーザー名¥AppData\Local\Programs\Python\Python39\testcode2-2.py", line 142, in OnExec 3 main() 4 , line 138, in main 5 send_line_notify(news) 6 , line 134, in send_line_notify 7 requests.post(line_notify_api, headers = headers, data = data) 8, line 117, in post 9 return request('post', url, data=data, json=json, **kwargs) 10 in request 11 return session.request(method=method, url=url, **kwargs) 12line 542, in request 13 resp = self.send(prep, **send_kwargs) 14 line 655, in send 15 r = adapter.send(request, **kwargs) 16 line 439, in send 17 resp = conn.urlopen( 18 line 699, in urlopen 19 httplib_response = self._make_request( 20 line 394, in _make_request 21 ", line 239, in request 22 super(HTTPConnection, self).request(method, url, body=body, headers=headers) 23 , line 1255, in request 24 self._send_request(method, url, body, headers, encode_chunked) 25", line 1296, in _send_request 26 self.putheader(hdr, value) 27 conn.request(method, url, **httplib_request_kw) 28 , line 224, in putheader 29 _HTTPConnection.putheader(self, header, *values) 30 File "C:\Users\ユーザー名\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 1228, in putheader 31 values[i] = one_value.encode('latin-1') 32UnicodeEncodeError: 'latin-1' codec can't encode characters in position 8-13: ordinal not in range(256)

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

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

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

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

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

guest

回答1

0

ベストアンサー

質問内容が3点あるのですかね?

1. UnicodeEncodeError

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 8-13: ordinal not in range(256)

次の引用が参考になるでしょうか?

r = requests.post('http://httpbin.org/post', data=a.encode('utf-8')) # Works fine.
https://github.com/psf/requests/issues/1822

2. カウント機能

・カウント機能が機能しておらず、記事数指定が出来ない及び、それらはVS Codeのデバッグ機能をすり抜けてしまう

py

1for title ,date ,url in zip(news_title, news_date, news_urls): 2 3 if int(count) > int(stop_count): 4 break 5 elif count <= 13: 6 news += '{} ({}) {}'.format(title, date, url) + '\r\n' 7 else: 8 news2 += '{} ({}) {}'.format(title, date, url) + '\r\n' 9 10count += 1

wxPythonを使ったことがないのですが・・
気になったのはcountのインクリメントはこの場所(インデント)で正しそうでしょうか?

3. パワーシェル(ターミナル)上でエラー

・VS Codeのpython上ではエラーが起きないが、パワーシェル(ターミナル)上で実行すると更に下のエラー文が出てきてしまう

上記1.のエラーのことですかね?

他に気になったこと

ソースコードにLINEのトークンとか記載してしまうと悪戯されてしまうこともあるのではないかと思いました・・

投稿2022/01/22 02:25

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

S.katou

2022/01/22 03:01

ご指摘ありがとうございます! 1件目、確認してみます 2件目、移動させて確認してみます 3件目、ご指摘の通りのエラー文でございます ※Lineトークン変更しました!ありがとうございます!
S.katou

2022/01/22 06:46

時間が掛かってしまいましたが、確認する事が出来ました。 1件目、3件目の原因としましては、(ユーザー名)フォルダから.pyファイルを実行した為のエンコードエラーでした。 こちらが原因でした C:\Users\(ユーザー名)py -----.py 正しくは C:\Users\ユーザー名\AppData\Local\Programs\Python\Python39> また、あろうことか、同じ名前で"(ユーザー名)フォルダ"と"pyhon39フォルダ"で2箇所に存在しており、同期もしてないので進行状況も1日ズレたコードを交互に繰り返していたようです。。。 こちらの確認不足で起きていたようで申し訳ございません。 2件目についてですが、原因が判明しました!! 最後の count += 1が、更に上のtry文のインデントに繋がっておりました!!(泣 for文と同じインデントに合わせるとカウント機能が活性化し、 最大25件まで取得可、13件を超えるとnew2へ書き込み、指定数でbreak することが確認できました! 自分で気付けずにお恥ずかしい限りですが無事に完成させることが出来ました。 更に精進していこうと思います! ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問