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

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

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

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1142閲覧

次ページを含む全てのWEBページをスクレイピングしたい。

trey_0329

総合スコア109

Python 3.x

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2018/10/11 16:54

度々の質問失礼致します。

下記車のECサイトの全40ページの車情報を取得したいと考えています。
そこでこちらでアドバイス頂き、私なりにカスタマイズしてスクレイピングしたいのですが、

  • CSVファイルには最初の二つほどが出力されるのみ
  • エラーが出る

UnicodeEncodeError: 'charmap' codec can't encode characters in position 1-5: character maps to <undefined>

  • エラーが出ているために、しっかり次ページにループできてるのか不明

という状況で数時間困っているため、どなたかにご教示お願いできればと思います。

下記、私の書いたコードです。

Python

1import csv 2import urllib 3import time 4from bs4 import BeautifulSoup 5 6 7url = 'https://dubai.dubizzle.com/motors/used-cars/?page=1' # 取得先URL 8num_pages = 40 # 取得ページ数 9request_interval = 1 # ページ取得間隔 10 11data = [] 12for i in range(0, num_pages + 1): 13 url = urllib.parse.urljoin(url, '?page=0'+str(i)) 14 print('getting page... ', url) 15 html = urllib.request.urlopen(url).read() 16 soup = BeautifulSoup(html, 'html.parser') 17 18for item_elems in soup.select('div.list-item-wrapper'): 19 # 年代、走行距離 20 li_elems = item_elems.select('ul.features > li') 21 year = li_elems[0].text.replace('Year: ', '') # 年代 22 km = li_elems[1].text.replace('Kilometers: ', '') # 走行距離 23 # メーカー、種類 24 breads = item_elems.select('p.breadcrumbs')[0].text 25 breads = [s.replace('\u202a', '').strip() for s in breads.split('>‪')] # \u202a は消す 26 maker = breads[1] 27 car_type = breads[2] 28 # 値段 29 price_elem = item_elems.select('div.price')[0] 30 price = price_elem.text.replace(',', '').replace('AED', '').strip() # , と AED は消す 31 # リンク 32 a_elem = item_elems.select('h3 a')[0] 33 car_url = urllib.parse.urljoin(url, a_elem.get('href')) 34 title = a_elem.text.strip() 35 36 data.append({ 37 'year': year, 38 'km': km, 39 'maker': maker, 40 'type': car_type, 41 'price': price, 42 'title': title, 43 'url': car_url 44 }) 45 46 47with open('output.csv', 'w') as f: 48 # 列の出力順序を規定 49 fields = ['title', 'url', 'maker', 'type', 'year', 'km', 'price'] 50 51 writer = csv.DictWriter(f, fieldnames=fields, quoting=csv.QUOTE_NONNUMERIC) 52 writer.writeheader() # ヘッダー出力 53 writer.writerows(data) # データ出力

何卒宜しくお願い致します。

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

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

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

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

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

guest

回答2

0

以前の質問を見るとwindows環境のようですが、windows環境でopen()を使うとデフォルトではencodingがcp932(いわゆるshift-jis)になります。

2. 組み込み関数 — Python 3.6.5 ドキュメント | open()

結果にcp932で表現できない文字列が含まれているため、書き出しに失敗しているということだと思います。

明示的に出力エンコーディングを指定すれば良いでしょう。

python

1with open('output.csv', 'w', encoding='utf-8') as f: 2

投稿2018/10/11 23:45

hayataka2049

総合スコア30933

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

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

trey_0329

2018/10/12 04:44

こちら再度確認したところ、問題なく動きました。 ありがとうございます。 Google上でも同様の回答を見つけました。 今後事前に自分でしっかり調べてから質問するよう気をつけます。
guest

0

自己解決

下記で解決いたしました。
ご協力頂いた方、誠にありがとうございました。

import csv import urllib import time from bs4 import BeautifulSoup url = 'https://dubai.dubizzle.com/motors/used-cars/?page=1' # 取得先URL num_pages = 4 # 取得ページ数 request_interval = 1 # ページ取得間隔 data = [] for i in range(0, num_pages + 1): url = urllib.parse.urljoin(url, '?page=0'+str(i)) print('getting page... ', url) html = urllib.request.urlopen(url).read() soup = BeautifulSoup(html, 'lxml') # 自分の環境では、lxml が使えなかったので、以下の 'html.parser' を使いました。 # soup = BeautifulSoup(html, 'html.parser') a_elems = soup.select('div.item-name > a') for item_elems in soup.select('div.list-item-wrapper'): # 年代、走行距離 li_elems = item_elems.select('ul.features > li') year = li_elems[0].text.replace('Year: ', '') # 年代 km = li_elems[1].text.replace('Kilometers: ', '') # 走行距離 # メーカー、種類 breads = item_elems.select('p.breadcrumbs')[0].text breads = [s.replace('\u202a', '').strip() for s in breads.split('>‪')] # \u202a は消す maker = breads[1] car_type = breads[2] # 値段 price_elem = item_elems.select('div.price')[0] price = price_elem.text.replace(',', '').replace('AED', '').strip() # , と AED は消す # リンク a_elem = item_elems.select('h3 a')[0] car_url = urllib.parse.urljoin(url, a_elem.get('href')) title = a_elem.text.strip() data.append({ 'year': year, 'km': km, 'maker': maker, 'type': car_type, 'price': price, 'title': title, 'url': car_url }) with open('output.csv', 'w', encoding='utf-8') as f: # 列の出力順序を規定 fields = ['title', 'url', 'maker', 'type', 'year', 'km', 'price'] writer = csv.DictWriter(f, fieldnames=fields, quoting=csv.QUOTE_NONNUMERIC) writer.writeheader() # ヘッダー出力 writer.writerows(data) # データ出力 print('complete')

投稿2018/10/12 16:57

trey_0329

総合スコア109

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問