已经完成的抓取会抓取页面上的所有内容。我想将抓取限制在某个部分

Posted

技术标签:

【中文标题】已经完成的抓取会抓取页面上的所有内容。我想将抓取限制在某个部分【英文标题】:Already complete scraping scrapes everything on the page. I would like to limit the scraping to only a certain section 【发布时间】:2022-01-06 15:53:57 【问题描述】:

我放置了我拥有的完整且功能正常的抓取的代码。成功抓取页面上的所有元素。

但是,我只想使用与抓取相同的元素抓取页面的一小部分。这个有限的部分已经连同页面的所有元素一起被正确地刮掉了,但我想只刮掉它而不是“全部+它”。链接是here

页面上有4个表格,但我想只抓取一个,即名为“Programma”的表格,即html部分“event-summary event” “联赛静态事件摘要联赛”。但本节只有最后一轮的元素(第 14 场比赛)。仅限第 14 场比赛。没有第 15 轮。很明显,随着页面轮次的每次更新,最后一轮也总是被刮掉。

所以我需要插入一些东西,让抓取理解只下载该部分和最后一轮的元素(它已经拥有和抓取)。

代码已经完成并且工作正常,所以我不是在寻找代码服务,而是为了告诉我如何将抓取限制在上面提到的部分。刮削是在 Selenium 中进行的。我想坚持使用 Selenium 和我的代码,因为它已经可以正常工作且完整。谢谢

import selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Firefox()
driver.get("url")
driver.implicitly_wait(12)
#driver.minimize_window()

wait = WebDriverWait(driver, 10)


all_rows = driver.find_elements(By.CSS_SELECTOR, "div[class^='event__round'],div[class^='event__match']")

current_round = '?'

for bundesliga in all_rows:
    classes = bundesliga.get_attribute('class')
    #print(classes)

    if 'event__round' in classes:
        #round = row.find_elements(By.CSS_SELECTOR, "[class^='event__round event__round--static']")
        #current_round = row.text  # full text `Round 20`

        current_round = bundesliga.text.split(" ")[-1]  # only `20` without `Round`   
                
    else:       
        datetime = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__time']")

        #Divide la data e l'ora
        date, time = datetime.text.split(" ")
        date = date.rstrip('.')  # right-strip to remove `.` at the end of date

        
        team_home = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__participant event__participant--home']")            
        team_away = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__participant event__participant--away']")
        score_home = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__score event__score--home']")
        score_away = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__score event__score--away']")
        
 
        bundesliga = [current_round, date, time, team_home.text, team_away.text, score_home.text, score_away.text]
        bundesliga.append(bundesliga)
        print(bundesliga)

【问题讨论】:

仍然找不到html部分“event-summary event”或“leagues-static event-summary-leagues” @DebanjanB 去它说“Programma”的地方。上面写着 Programma 和 Giornata 14 的表格。看我的截图 pasteboard.co/Fj4qU7AMmZnk.jpg 是的,现在可以找到event event--summary 类。所以你只想刮最后几轮。 @DebanjanB 是的,“程序”中的最后一轮(没有结果的那一轮,因此还有待播放)。但它也说第 15 轮,我不想要 15。只有 14。所以很明显,随着页面上的每一轮更新,我只会刮掉最后一轮。元素与我在抓取中的元素相同。谢谢:) @DebanjanB 你能帮帮我吗?谢谢 【参考方案1】:

我认为您需要做的就是限制all_rows 变量。一种方法是使用文本找到您要查找的选项卡,然后获取父元素。

import selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException

driver = webdriver.Firefox()
driver.get("https://www.someurl/some/other/page")
driver.implicitly_wait(12)
#driver.minimize_window()

wait = WebDriverWait(driver, 10)


# all_rows = driver.find_elements(By.CSS_SELECTOR, "div[class^='event__round'],div[class^='event__match']")
############### UPDATE ####################
def parent_element(element):
    return element.find_element(By.XPATH, './..')
programma_element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.XPATH, "//div[text()='Programma']")))

programma_element_p1 = parent_element(programma_element)
programma_element_p2 = parent_element(programma_element_p1)
programma_element_p3 = parent_element(programma_element_p2)

all_rows = programma_element_p3.find_elements(By.CSS_SELECTOR, "div[class^='event__round'],div[class^='event__match']")
filter_rows = []

for row in all_rows:
    if "event__match--last" in row.get_attribute('class'):
        filter_rows.append(row)
        break
    else:
        filter_rows.append(row)

############### UPDATE ####################
current_round = '?'

for bundesliga in filter_rows:
    classes = bundesliga.get_attribute('class')
    #print(classes)

    if 'event__round' in classes:
        #round = row.find_elements(By.CSS_SELECTOR, "[class^='event__round event__round--static']")
        #current_round = row.text  # full text `Round 20`

        current_round = bundesliga.text.split(" ")[-1]  # only `20` without `Round`   
                
    else:       
        datetime = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__time']")

        #Divide la data e l'ora
        date, time = datetime.text.split(" ")
        date = date.rstrip('.')  # right-strip to remove `.` at the end of date

        
        team_home = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__participant event__participant--home']")            
        team_away = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__participant event__participant--away']")
        # score_home = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__score event__score--home']")
        # score_away = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__score event__score--away']")

        try:
            score_home = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__score event__score--home']")
        except (TimeoutException, NoSuchElementException):
            MyObject = type('MyObject', (object,), )
            score_home = MyObject()
            score_home.text = "-"
        try:
            score_away = bundesliga.find_element(By.CSS_SELECTOR, "[class^='event__score event__score--away']")
        except (TimeoutException, NoSuchElementException):
            MyObject = type('MyObject', (object,), )
            score_away = MyObject()
            score_away.text = "-"
        
 
        bundesliga = [current_round, date, time, team_home.text, team_away.text, score_home.text, score_away.text]
        bundesliga.append(bundesliga)
        print(bundesliga)

【讨论】:

我发现你的代码,虽然很特别,但在第 14 轮和第 15 轮都被刮掉了。事实上,我注意到了第 15 轮的科隆-奥古斯塔比赛。你的代码可能会分散注意力。正如您在问题中看到的那样,我用红色突出显示我只想在第 14 轮刮。我想自己解决它,但我无法做到,因为我是 Python 的初学者。你能纠正你的答案吗?你太棒了! @Johan.D.只是为了确认您要暂时排除第 15 轮,然后在第 15 轮和第 16 轮在表中时将其包括在内? @Johan.D.添加了更多更新 我得到一个错误:除了 TimeoutException: NameError: TimeoutException 没有定义。我确认我要排除第 15 轮。我不明白您的意思是“然后在第 15 轮和第 16 轮在表中时包含它”。几天后网页将更新,第 14 轮将消失,所以我想刮下一轮将是 15(只有 15,但不是第 16 轮)。现在我只想刮 14但不是 15。更新后,下周我想只刮 15 而不是 16。然后我又想刮 16 而不是 17,依此类推。 @Johan.D.感谢您的确认,我更新了答案以包含 TimeoutException 的导入。

以上是关于已经完成的抓取会抓取页面上的所有内容。我想将抓取限制在某个部分的主要内容,如果未能解决你的问题,请参考以下文章

如何用Java抓取网页的具体内容

如何使用python和beautifulsoup4循环抓取网站中多个页面的数据

使用 selenium 在 LinkedIn 上抓取个人资料网址

如何使用 Selenium 等待页面上的元素可见(然后转到其他内容)?

网页抓取 - 如何识别网页上的主要内容

如何使用 Python 抓取 PDF;仅限特定内容