PDG*_*ill 5 html python selenium xpath web-scraping
我正在尝试从网站上抓取一些营养数据,到目前为止一切似乎都进展顺利,直到我遇到格式略有不同的页面。
使用 selenium 和这样的行,返回一个空列表:
values = browser.find_elements_by_class_name('size-12-fl-oz' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value')
Run Code Online (Sandbox Code Playgroud)
print 会返回这个:
[]
[]
[]
[]
[]
Run Code Online (Sandbox Code Playgroud)
但如果我定义了元素位置,那么它就可以正常工作:
kcal = data.find_elements_by_xpath("(.//div[@class='size-12-fl-oz nutrition-value' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value'])[position()=1]").text
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,当我迭代时,页面与页面之间的元素不相同。因此,如果位置 9 不存在 div,则会抛出错误。
现在,当我返回并尝试编辑代码来执行 a 时try/catch
,我得到:
AttributeError:“列表”对象没有属性“find_element_by_xpath”
或者
AttributeError:“列表”对象没有属性“find_elements_by_xpath”
这是代码,其中有我在来回测试中注释掉的区域。
import requests, bs4, urllib2, csv
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import NoSuchElementException
browser = webdriver.Firefox()
...
#Loop on URLs to get Nutritional Information from each one.
with open('products.txt') as f:
for line in f:
url = line
# url = 'http://www.tapintoyourbeer.com/index.cfm?id=3'
browser.get(url)
with open("output.csv", "a") as o:
writeFile = csv.writer(o)
browser.implicitly_wait(3)
product_name = browser.find_element_by_tag_name('h1').text.title() #Get product name
size = browser.find_element_by_xpath("(//div[@class='dotted-tab'])").text #Get product size
data = browser.find_elements_by_xpath("//table[@class='beer-data-table']")
# values=[]
# values = browser.find_elements_by_class_name('size-12-fl-oz' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value')
try:
# values = data.find_elements_by_xpath("(.//div[@class='size-12-fl-oz nutrition-value' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value'])")
kcal = data.find_element_by_xpath("(.//div[@class='size-12-fl-oz nutrition-value' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value'])[position()=1]").text
kj = data.find_element_by_xpath("(.//div[@class='size-12-fl-oz nutrition-value' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value'])[position()=3]").text
fat = data.find_element_by_xpath("(.//div[@class='size-12-fl-oz nutrition-value' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value'])[position()=5]").text
carbs = data.find_element_by_xpath("(.//div[@class='size-12-fl-oz nutrition-value' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value'])[position()=7]").text
protein = data.find_element_by_xpath("(.//div[@class='size-12-fl-oz nutrition-value' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value'])[position()=9]").text
values = [kcal, kj, fat, carbs, protein]
print values
writeFile.writerow([product_name] + [size] + values)
except NoSuchElementException:
print("No Protein listed")
browser.quit()
Run Code Online (Sandbox Code Playgroud)
我之前让它生成一个列表,并输出到 CSV,但有时,位置计数会出现错误。
[u'Budweiser', u'12 FL OZ', u'145.00', u'', u'', u'', u'']
[u"Beck'S", u'12 FL OZ', u'146.00', u'610.86', u'0.00', u'10.40', u'1.80']
[u'Bud Light', u'12 FL OZ', u'110.00', u'460.24', u'0.00', u'6.60', u'0.90']
[u'Michelob Ultra', u'12 FL OZ', u'95.00', u'397.48', u'0.00', u'2.60', u'0.60']
[u'Stella Artois', u'100 ML', u'43.30', u'KCAL/100 ML', u'181.17', u'KJ/100 ML', u'0.00']
Run Code Online (Sandbox Code Playgroud)
当特定页面上不存在位置 9 时,问题就开始了。
对于如何解决这个头痛问题有什么建议吗?我需要为不同的页面和尺寸设置案例吗?
我很感激你的帮助。
实际上find_elements()
返回列表WebElement
或空列表。您将此结果存储到列表变量 name 中data
。
AttributeError:“列表”对象没有属性“find_element_by_xpath”
AttributeError:“列表”对象没有属性“find_elements_by_xpath”
发生这种情况是因为您将发现嵌套WebElement
在data
列表中,这就是您调用 asdata.find_element_by_xpath()
或 的原因data.find_elements_by_xpath()
,这绝对是错误的。
实际上find_element()
or是用来搜索页面上下文或代替 的上下文find_elements()
上的元素。WebElement
list
WebElement
因此,您应该尝试从列表中查找个体data
,然后WebElement
使用此元素上下文查找进一步嵌套,如下所示:-
if len(data) > 0:
#now find desire element using index
individual_element = data[0]
#now you can find further nested single element using find_element() or list of elements using find_elements() at individual_element context
kcal = individual_element.find_element_by_xpath("(.//div[@class='size-12-fl-oz nutrition-value' or 'size-330-ml hide nutrition-value' or 'size-8-fl-oz nutrition-value'])[position()=1]").text
----------------------------
----------------------------
Run Code Online (Sandbox Code Playgroud)