pythonでweblioスクレイピング②

:::note warn
断り
これは4年ほど前に書いた記事です。
当時は別のアカウントで公開していましたが、アカウントを移行することになったので、こちらに改めて投稿しています。
内容は学部生の頃に書いたもので、コードもだいぶ拙いところがあると思いますが、その点はご容赦ください。
:::

とりあえず全文
```python:scraping.py
import re
import time
import pprint
from bs4 import BeautifulSoup

url = 'https://ejje.weblio.jp/content/prefer+to'
r = requests.get(url)
bsObj = BeautifulSoup(r.content,'lxml')
origin = bsObj.find_all("span",{"class":"content-explanation ej"})

err_url = []
try:
    meanings = ','.join(str(origin).split('  ')[-1].split('<')[0].split('、')[0:3])
except:
    err_url.append(url)
    print('失敗' + err_url[-1])
    print("htmlが無効だ")
    # continue

eng = url.split('/')[-1]
eng = re.sub(r"[^a-zA-Z0-9]"," ",eng)

pprint.pprint(eng + ':' + meanings)
```
# 細かく説明していくー
```python:scraping.py
url = 'https://ejje.weblio.jp/content/prefer+to'
r = requests.get(url)
bsObj = BeautifulSoup(r.content,'lxml')

origin = bsObj.find_all("span",{"class":"content-explanation ej"})
```
`url`にweblioのURLを代入します。(最終的には前回の作ったurlsを使います。)
htmlパース用のオブジェクトを`r`に代入します
パーサーを`lxml`に指定します


下の画像を見るとわかる通り、和訳の部分は"content-explanation ej"というクラスのspanタグに格納されているので`("span",{"class":"content-explanation ej"})`となります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1637183/2bb78a3f-b80a-2e63-7537-dedcf27ee6a4.png)
出力すると以下のようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1637183/a3a1813a-376d-4ab8-fe54-60b9e43e66e6.png)
#

```python:scraping.py
meanings = []
err_url
try:
    meanings = ','.join(str(origin).split('  ')[-1].split('<')[0].split('、')[0:3])
except:
    err_url.append(url)
    print('失敗' + err_url[-1])
    print("htmlが無効だ")
    # continue
```
`meanings = ','.join(str(origin).split('  ')[-1].split('<')[0].split('、')[0:3])`
を分けて書くと以下のようになります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1637183/e725f934-5290-287d-cce1-a9936767a91e.png)

`origin`の余計な記号や文字をsplit関数を使ってのぞいて、それをjoin関数を用いて「,」で連結します。
`str(origin).split('  ')[-1]`

は2個のスペースで区切った末尾要素のことです。indexを-1とすると末尾を指定できます。
また、なぜ2個の空欄で区切るのかというと、例えば下のcameのように意味の欄にスペースが入ってしまっている場合に挙動がおかしくなってしまうからです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1637183/abde9951-5d1d-cb06-9890-adeb74a620d1.png)

except(例外処理)は、単語の意味がうまく抽出できなかった時にエラー文を出力する処理が書いてあります。
文自体は何でもいいです。ただし何にもないと、不明な段落がある という文法エラーが出てしまいます。

`continue`がコメントアウトされていますが、第一回と今回のコードを結合させ、ループで処理をする際には必要になります。
#
```python:scraping.py
eng = url.split('/')[-1]
eng = re.sub(r"[^a-zA-Z0-9]"," ",eng)
```
訳す前の英単語をurlの文字列から取得します
urlみると`https://ejje.weblio.jp/content/prefer+to`となっています。
「/」で区切って末尾要素を取り出します。

`eng = re.sub(r"[^a-zA-Z0-9]"," ",eng)`
は正規表現といって文字列から余分な記号を取り除きます。今回は「＋」を取り除きます
#
## 第一回と今回のコードを結合
```python:scraping.py
import json
import getpass
import requests
from bs4 import BeautifulSoup
import re
import time
import pprint

bookmark_path = '\\Users\\PCのユーザ名\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks'

with open(bookmark_path,encoding = 'utf-8_sig') as f:
    bookmark_data = json.load(f)

bookmarks = bookmark_data['roots']['bookmark_bar']['children'][0]['children']

def get_weblio_url(bookmark):
    if 'Weblio' in bookmark['name']:#Wは大文字
        return bookmark['url']

urls = filter(lambda url:url is not None, list(map(get_weblio_url,bookmarks)) )

for url in list(urls):
    try:
        r = requests.get(url)
        bsObj = BeautifulSoup(r.content,'lxml')
    except: 
        print("urlが無効だ")

    meaning = []
    err_url = []
    origin = bsObj.find_all("span",{"class":"content-explanation ej"})

    err_url = []
    try:
        meanings = ','.join(str(origin).split('  ')[-1].split('<')[0].split('、')[0:3])
    except:
        err_url.append(url)
        print('失敗' + err_url[-1])
        print("htmlが無効だ")
        continue
    eng = url.split('/')[-1]
    eng = re.sub(r"[^a-zA-Z0-9]"," ",eng)
    time.sleep(3)
    pprint.pprint(eng + ':' + meanings)
```