python - 使用多个链接之间的特定链接时,脚本会引发错误

标签 python python-3.x selenium web-scraping scrapy

我使用 scrapy 结合 selenium 编写了一个脚本,用于从网页解析不同公司 CEO 的姓名。您可以在登陆页面找到不同公司的名称。但是,一旦您点击公司名称链接,您就可以获得 CEO 的姓名。

以下脚本可以解析不同公司的链接,并使用这些链接来抓取除第二家公司之外的 CEO 的姓名。 当脚本尝试使用第二家公司的链接解析 CEO 的姓名时,遇到陈旧元素引用错误。即使脚本在途中遇到该错误,它也会以正确的方式获取其余结果。再一次 - 它仅在使用第二个公司链接解析信息时抛出错误。多么奇怪!!

The webpage link

这是我迄今为止尝试过的:

import scrapy
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

class FortuneSpider(scrapy.Spider):

    name = 'fortune'
    url = 'http://fortune.com/fortune500/list/'

    def start_requests(self):
        self.driver = webdriver.Chrome()
        self.wait = WebDriverWait(self.driver,10)
        yield scrapy.Request(self.url,callback=self.get_links)

    def get_links(self,response):
        self.driver.get(response.url)
        for item in self.wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '[class*="searchResults__title--"]'))):
            company_link = item.find_element_by_css_selector('a[class*="searchResults__cellWrapper--"]').get_attribute("href")
            yield scrapy.Request(company_link,callback=self.get_inner_content)

    def get_inner_content(self,response):
        self.driver.get(response.url)
        chief_executive = self.wait.until(EC.presence_of_element_located((By.XPATH, '//tr[td[.="CEO"]]//td[contains(@class,"dataTable__value--")]/div'))).text
        yield {'CEO': chief_executive}

这是我得到的结果类型:

Jeffrey P. Bezos

raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
  (Session info: chrome=76.0.3809.132)

Darren W. Woods
Timothy D. Cook
Warren E. Buffett
Brian S. Tyler
C. Douglas McMillon
David S. Wichmann
Randall L. Stephenson
Steven H. Collis
and so on------------

How can I fix the error that my script encounters while dealing with the second company link?

PS 我可以使用他们的 api 来获取所有信息,但我很好奇为什么上面的脚本会面临这个奇怪的问题。

最佳答案

稍微修改一下的方法应该可以让您从该网站获得所有所需的内容,而不会出现任何问题。您需要做的就是将所有目标链接存储为 get_links() 中的列表。方法及使用returnyield同时回调 get_inner_content()方法。您还可以禁用图像以使脚本稍微快一些。

以下尝试应该会为您带来所有结果:

import scrapy
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 scrapy.crawler import CrawlerProcess

class FortuneSpider(scrapy.Spider):

    name = 'fortune'
    url = 'http://fortune.com/fortune500/list/'

    def start_requests(self):
        option = webdriver.ChromeOptions()
        chrome_prefs = {}
        option.experimental_options["prefs"] = chrome_prefs
        chrome_prefs["profile.default_content_settings"] = {"images": 2}
        chrome_prefs["profile.managed_default_content_settings"] = {"images": 2}

        self.driver = webdriver.Chrome(options=option)
        self.wait = WebDriverWait(self.driver,10)
        yield scrapy.Request(self.url,callback=self.get_links)

    def get_links(self,response):
        self.driver.get(response.url)
        item_links = [item.get_attribute("href") for item in self.wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '[class*="searchResults__title--"] a[class*="searchResults__cellWrapper--"]')))]
        return [scrapy.Request(link,callback=self.get_inner_content) for link in item_links]

    def get_inner_content(self,response):
        self.driver.get(response.url)
        chief_executive = self.wait.until(EC.presence_of_element_located((By.XPATH, '//tr[td[.="CEO"]]//td[contains(@class,"dataTable__value--")]/div'))).text
        yield {'CEO': chief_executive}

if __name__ == "__main__":
    process = CrawlerProcess()
    process.crawl(FortuneSpider)
    process.start()

或者使用yield :

def get_links(self,response):
    self.driver.get(response.url)
    item_links = [item.get_attribute("href") for item in self.wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '[class*="searchResults__title--"] a[class*="searchResults__cellWrapper--"]')))]
    for link in item_links:
        yield scrapy.Request(link,callback=self.get_inner_content) 

关于python - 使用多个链接之间的特定链接时,脚本会引发错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58051328/

相关文章:

python - 在 Django 数据迁移中打印到 stdout 或 stderr 是否可以?如果是这样,如何?

python - PyTables:索引大型数组的多个维度

python - SQLAlchemy 警告 文本列表达式应该显式声明吗?

python - Ctrl+C 取消进程后发送一次 EOFError

javascript - Selenium WebDriver Python重新加载html而不刷新页面

java - 在 web 元素中查找动态样式属性

python - 对身份感到困惑并且是运算符(operator)

python - 两个分类交叉熵之间的凸组合

python - 如何使用 PyUpdater 从 USB 闪存驱动器进行更新

css - 如何使用 intern js 截取 DOM 元素的屏幕截图?