この抽出が例ではうまく機能するのに、実際のURLでは機能しないのはなぜですか?
Aug 22 2020
href
内にあるクラスa
内のコンテンツを抽出しようとしてい<td class="DataZone">
ます。以下の例で動作します
from bs4 import BeautifulSoup
text = '''
<td class="DataZone"><div id="Content_CA_DI_0_DataZone">
<div style="font:bold 8pt 'Courier New';letter-spacing:-1px">
<a href="Browse-A">A</a> <a href="Browse-B">B</a> <a href="Browse-C">C</a> <a href="Browse-D">D</a>
</div>
</div></td>
'''
soup = BeautifulSoup(text, 'html.parser')
[tag.attrs['href'] for tag in soup.select('td.DataZone a')]
、結果は['Browse-A', 'Browse-B', 'Browse-C', 'Browse-D']
です。実際のURLに適用すると、残念ながら機能しません
import requests
session = requests.Session()
from bs4 import BeautifulSoup
url = 'https://www.thefreedictionary.com'
headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'}
r = session.get(url, headers = headers)
soup = BeautifulSoup(r.content, 'html.parser')
[tag.attrs['href'] for tag in soup.select('td.DataZone a')]
エラーを返します
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-12-0a06dde2d97b> in <module>
4 soup = BeautifulSoup(r.content, 'html.parser')
5
----> 6 [tag.attrs['href'] for tag in soup.select('td.DataZone a')]
<ipython-input-12-0a06dde2d97b> in <listcomp>(.0)
4 soup = BeautifulSoup(r.content, 'html.parser')
5
----> 6 [tag.attrs['href'] for tag in soup.select('td.DataZone a')]
KeyError: 'href'
明らかに、URLのソースは例に似ています

このようなエラーが発生する理由を説明してください。
更新:[x['href'] for x in soup.select('td.DataZone a[href^=Browse]')]
正常に動作するのは私にとって奇妙ですが、そうではありません[x['href'] for x in soup.select('td.DataZone a')]
。この問題についても詳しく説明してください。
回答
2 AndrejKesely Aug 22 2020 at 17:46
多くtd.Datazone
のタグがあり、タグの1つに<a>Google+</a>
-がないため、エラーが発生しますhref
。
次の属性を持つタグtd.DataZone a[href]
のみを選択するように選択できます。<a>
href
print( [tag.attrs['href'] for tag in soup.select('td.DataZone a[href]')] )
2 Ava Aug 22 2020 at 17:12
すべての<a>
タグにhref
属性があるわけではないようです。代わりにこれを試してください。
l = [tag.attrs['href'] for tag in soup.select('td.DataZone a') if 'href' in tag.attrs]
print(*l, sep = '\n')
これを行うこともできます。
l = [tag.attrs['href'] for tag in soup.select('td.DataZone a[attr="href"]')]
print(*l, sep = '\n')
2 αԋɱҽԃαмєяιcαη Aug 22 2020 at 17:10
ここで、間違ったCSS
セレクターを使用している点。
import requests
from bs4 import BeautifulSoup
def main(url):
r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser')
target = [x['href'] for x in soup.select("a[href^=Browse]")]
print(target)
main("https://www.thefreedictionary.com/")
または:
target = [x for x in soup.select("td.DataZone a[href^=Browse]")]
出力:
['Browse-A', 'Browse-B', 'Browse-C', 'Browse-D', 'Browse-E', 'Browse-F', 'Browse-G', 'Browse-H', 'Browse-I', 'Browse-J', 'Browse-K', 'Browse-L', 'Browse-M', 'Browse-N', 'Browse-O', 'Browse-P', 'Browse-Q', 'Browse-R', 'Browse-S', 'Browse-T', 'Browse-U', 'Browse-V', 'Browse-W', 'Browse-X', 'Browse-Y', 'Browse-Z']
コメントのユーザー要件に基づいて更新:
import requests
from bs4 import BeautifulSoup
def main(url):
r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser')
for item in soup.select("td.DataZone"):
for x in item.findAll(href=True):
print(x['href'])
main("https://www.thefreedictionary.com/")