【问题标题】:Only items from first Beautiful Soup object are being added to my lists只有来自第一个 Beautiful Soup 对象的项目被添加到我的列表中
【发布时间】:2021-01-30 11:25:57
【问题描述】:

我怀疑这不是很复杂,但我看不出来。我正在使用 Selenium 和 Beautiful Soup 来解析 Petango.com。数据将用于帮助当地避难所了解他们在不同指标上与其他地区避难所的比较。所以接下来将获取这些数据框并进行一些分析。 我从不同的模块中获取详细 url 并在此处导入列表。 我的问题是,我的列表只显示来自第一只狗的 HTML 的值。我正在逐步检查并注意到我的 len 对于汤迭代是不同的,所以我意识到我的错误是在那之后的某个地方,但我不知道如何解决。 到目前为止,这是我的代码(运行整个过程与使用缓存页面)

from bs4 import BeautifulSoup
from selenium import webdriver
import pandas as pd
from Petango import pet_links
headings = []
values = []
ShelterInfo = []
ShelterInfoWebsite = []
ShelterInfoEmail = []
ShelterInfoPhone = []
ShelterInfoAddress = []
Breed = []
Age = []
Color = []
SpayedNeutered = []
Size = []
Declawed = []
AdoptionDate = []

# to access sites, change url list to pet_links (break out as needed) and change if false to true.  false looks to the html file
url_list = (pet_links[4], pet_links[6], pet_links[8])
#url_list = ("Petango.html", "Petango.html", "Petango.html")
for link in url_list:
    page_source = None
    if True:
        #pet page = link should populate links from above, hard code link was for 1 detail page, =to hemtl was for cached site
        PetPage = link
        #PetPage = 'https://www.petango.com/Adopt/Dog-Terrier-American-Pit-Bull-45569732'
        #PetPage = Petango.html
        PetDriver = webdriver.Chrome(executable_path='/Users/paulcarson/Downloads/chromedriver')
        PetDriver.implicitly_wait(30)
        PetDriver.get(link)
        page_source = PetDriver.page_source
        PetDriver.close()
    else:
        with open("Petango.html",'r') as f:
            page_source = f.read()
    PetSoup = BeautifulSoup(page_source, 'html.parser')
    print(len(PetSoup.text))

    #get the details about the shelter and add to lists
    ShelterInfo.append(PetSoup.find('div', class_ = "DNNModuleContent ModPethealthPetangoDnnModulesShelterShortInfoC").find('h4').text)

    ShelterInfoParagraphs = PetSoup.find('div', class_ = "DNNModuleContent ModPethealthPetangoDnnModulesShelterShortInfoC").find_all('p')
    First_Paragraph = ShelterInfoParagraphs[0]
    if "Website" not in First_Paragraph.text:
        raise AssertionError("first paragraph is not about site")
    ShelterInfoWebsite.append(First_Paragraph.find('a').text)

    Second_Paragraph = ShelterInfoParagraphs[1]
    ShelterInfoEmail.append(Second_Paragraph.find('a')['href'])

    Third_Paragraph = ShelterInfoParagraphs[2]
    ShelterInfoPhone.append(Third_Paragraph.find('span').text)

    Fourth_Paragraph = ShelterInfoParagraphs[3]
    ShelterInfoAddress.append(Fourth_Paragraph.find('span').text)

    #get the details about the pet

    ul = PetSoup.find('div', class_='group details-list').ul  # Gets the ul tag

    li_items = ul.find_all('li')  # Finds all the li tags within the ul tag

    for li in li_items:
        heading = li.strong.text
        headings.append(heading)

        value = li.span.text

        if value:
            values.append(value)
        else:
            values.append(None)
    Breed.append(values[0])
    Age.append(values[1])
    print(Age)
    Color.append(values[2])
    SpayedNeutered.append(values[3])
    Size.append(values[4])
    Declawed.append(values[5])
    AdoptionDate.append(values[6])

ShelterDF = pd.DataFrame(
    {
      'Shelter': ShelterInfo,
      'Shelter Website': ShelterInfoWebsite,
      'Shelter Email': ShelterInfoEmail,
      'Shelter Phone Number': ShelterInfoPhone,
      'Shelter Address': ShelterInfoAddress
    })

PetDF = pd.DataFrame(
    {'Breed': Breed,
     'Age': Age,
     'Color': Color,
     'Spayed/Neutered': SpayedNeutered,
     'Size': Size,
     'Declawed': Declawed,
     'Adoption Date': AdoptionDate
    })

print(PetDF)
print(ShelterDF)

从 print len 输出并随着循环的进行打印年龄值

12783
['6y 7m']
10687
['6y 7m', '6y 7m']
10705
['6y 7m', '6y 7m', '6y 7m']

有人可以指点我正确的方向吗?

感谢您的帮助!

保罗

【问题讨论】:

    标签: python selenium web-scraping beautifulsoup automation


    【解决方案1】:

    您需要在 BeautifulSoup 中将 find 方法更改为 find_all() 以便它定位所有元素。

    【讨论】:

    • 感谢您的建议,但我认为这还不够。我真的只想要它在每次汤迭代中找到的第一个。我的问题是它似乎只是从第一次通过中获取值而不是替换它(例如,soup1、values、soup 2 值等)。我尝试了 find_all,它抛出了一个错误,之后没有另一个值第一个让我觉得它只是通过一个汤对象。谢谢你的建议
    【解决方案2】:

    Values 是全局的,您只能将此列表中的第一个值附加到 Age

    Age.append(values[1])
    

    您的其他全局列表也存在同样的问题(静态索引是 1 还是 2 等...)。

    您需要一种方法来跟踪可能通过计数器使用的适当索引,或确定其他逻辑以确保添加当前值,例如与当前年龄,它是循环中的第二个 li 吗?或者只是附加PetSoup.select_one("[data-bind='text: age']").text

    看起来像每个感兴趣的项目,例如colour,spayed 包含 data-bind 属性,因此您可以使用具有适当属性值的那些来选择每个值并避免 li 元素的循环。

    例如current_colour = PetSoup.select_one("[data-bind='text: color']").text

    最好在使用.text访问之前设置一个变量并测试is not None

    【讨论】:

    • 谢谢!这让我朝着正确的方向前进。我最终重做了宠物变量,类似于您在上面构建它的方式以及我如何完成庇护所信息。 (添加 is not None,谢谢您的提示)它的工作方式与我期望的一样,为数据框提供了值。接下来,进行一些分析。再次感谢您的指导!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 2021-02-28
    • 2021-12-22
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多