【问题标题】:Getting error "pywintypes.error: (5, 'OpenClipboard', 'Access is denied.')"出现错误“pywintypes.error: (5, 'OpenClipboard', 'Access is denied.')”
【发布时间】:2019-05-04 18:20:42
【问题描述】:

我正在尝试使用 selenium 和 python 从this 站点获取纬度和经度。我也在使用win32lipboard。但是每当我运行我的代码时,它都会随机抛出这个错误pywintypes.error: (5, 'OpenClipboard', 'Access is denied.')

这是我的代码:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import csv
import win32clipboard

csvreader = csv.reader(open("master_data.csv", 'r'))

csvwriter = csv.writer(open('final_master_data.csv', 'w', newline=''))

headers = next(csvreader)
headers.append("latitude")
headers.append("longitude")
csvwriter.writerow(headers)

locations = list(csvreader)

chromedriver = 'C:\\Users\\UserName\\Downloads\\chromedriver.exe'
driver = webdriver.Chrome(chromedriver)
driver.get('http://www.whatsmygps.com')

for places in locations:
    place = places[6] + ", " + places[4] + ", " + places[2]

    location = driver.find_element_by_id("address")

    location.send_keys(Keys.CONTROL, 'a')
    location.send_keys(place)

    location.submit()

    time.sleep(3)

    lat_input = driver.find_element_by_id("latitude")
    lat_input.send_keys(Keys.CONTROL, 'a')
    lat_input.send_keys(Keys.CONTROL, 'c')

    win32clipboard.OpenClipboard()
    lat = win32clipboard.GetClipboardData()

    places.append(lat)

    win32clipboard.CloseClipboard()

    lon_input = driver.find_element_by_id("longitude")
    lon_input.send_keys(Keys.CONTROL, 'a')
    lon_input.send_keys(Keys.CONTROL, 'c')

    win32clipboard.OpenClipboard()
    lon = win32clipboard.GetClipboardData()
    win32clipboard.CloseClipboard()

    places.append(lon)
    print(places)

    csvwriter.writerow(places)

driver.close()

所以,每当我运行此代码时,它都会毫无问题地启动,它会读取 csv 文件并将位置名称输入此站点,然后开始从该站点复制纬度和经度并将其插入另一个 csv 文件。但一段时间后,它会随机抛出错误pywintypes.error: (5, 'OpenClipboard', 'Access is denied.')。从昨天开始我就找不到解决方案了。

更新:我正在使用 Anaconda,并且以管理员身份运行 anaconda shell,所以访问权限没有问题。

【问题讨论】:

  • 我不记得了,但driver.find_element_by_id("address").text不应该包含你想要的字符串吗?
  • @BarmakShemirani 我使用driver.find_element_by_id("address") 来通过id 获取元素,如果我们使用.text 属性,那么我们会得到文本。但是这个字段是输入字段,在这个字段中使用 selenium 我输入位置地址。这没有问题,当我复制并粘贴纬度和经度时,我遇到了问题。您可以通过访问网站本身来检查它。
  • 好吧,我弄糊涂了。看看您是否可以直接阅读driver.find_element_by_id("latitude").textlongitude 的相同内容
  • 我也试过了。但在这种情况下,它不会给你任何东西。如果您亲自检查,这将是很大的帮助。我在上面的脚本中给出了该网站的链接。

标签: python-3.x anaconda selenium-chromedriver pywin32


【解决方案1】:

如果剪贴板被另一个进程锁定,可能会出现拒绝访问错误。为避免 python 消息,您可以使用此 SO 链接中描述的 WinAPI 版本的剪贴板:https://stackoverflow.com/a/23285159/4603670


作为替代方案,使用需要 API 密钥的 BingMap。在撰写本文时,您可以在https://www.bingmapsportal.com 注册一个开发者帐户以获得免费的 API 密钥(我不确定配额)。
import pythoncom
import win32com.client
import json

pythoncom.CoInitialize()
winhttp = win32com.client.Dispatch('WinHTTP.WinHTTPRequest.5.1')

def bing_find_gps(addressLine, postalCode, country):

    q = 'http://dev.virtualearth.net/REST/v1/Locations?key='
    q = q + 'my_api_key'
    if country: q = q + '&countryRegion=' + country
    if postalCode: q = q + '&postalCode=' + postalCode
    if addressLine: q = q + '&addressLine=' + addressLine

    try:
        winhttp.Open('GET', q, False)
        winhttp.Send()
        if not winhttp.responseText:
            return 0
        list = json.loads(winhttp.responseText)
        if list['statusCode'] != 200:
            return 0
        gps = list['resourceSets'][0]['resources'][0]['point']['coordinates']
        if gps:
            return (1, gps[0], gps[1])
    except:
        return 0

res = bing_find_gps('One Microsoft Way, Redmond, WA, 98052-6399', '0', 'United States')
if res:
    print("lat/long %s, %s" % (res[1], res[2]))
res = bing_find_gps(0, '98052-6399', 'United States')
if res:
    print("lat/long %s, %s" % (res[1], res[2]))


或使用openstreetmap.org
address = "98052-6399" #Testing with Microsoft zip code
url = "https://nominatim.openstreetmap.org/search?format=json&q=" + address
winhttp.Open('GET', url, False)
winhttp.Send()
list = json.loads(winhttp.responseText)
print(list[0].get('lat'))
print(list[0].get('lon'))

预期输出:

Latitude: 47.670119 
Longitude: -122.118237

或者您也可能希望完全避免复制元素,使用get_attribute('value') 读取latitudelongitude 中的值。示例:

chromedriver = 'C:\\Users\\UserName\\Downloads\\chromedriver.exe'
driver = webdriver.Chrome(chromedriver)
driver.get('http://www.whatsmygps.com')

element = driver.find_element_by_id("address")
element.send_keys(Keys.CONTROL, 'a')
#enter Microsoft's zip code
element.send_keys('98052-6399')
element.submit()
time.sleep(3)

lat_input = driver.find_element_by_id("latitude")
print('latitude: ')
print(lat_input.get_attribute('value'))

lon_input = driver.find_element_by_id("longitude")
print('longitude: ')
print(lon_input.get_attribute('value'))

driver.close()

【讨论】:

  • 谢谢,它成功了。我使用了您的解决方案,即get_attribute('value'),它奏效了。我还没有检查你提供的链接,但我会稍后再做。再次感谢。
  • 请注意,以上网站使用谷歌API,服务不保证(目前已被屏蔽,表示已达到密钥所有者的最大配额)。您可以直接使用 Google API,但我不清楚 Google 目前的服务条款是什么(我认为您必须付费)。请参阅编辑以改用免费的 openstreetmap.org
  • 一开始我也想用openstreetmap,但就我而言,有很多城市openstreetmap没有提供任何数据。示例:这是我的地址:印度安达曼和尼科巴群岛的 Adojig。现在,如果您尝试使用 openstreetmap 获取详细信息,它不会为您提供任何详细信息,但使用我上面提到的站点,它会为您提供 lat 和 lon。这就是我选择它的原因。
  • 但是正如您提到的那样,该网站还限制了一些点击后的点击量。所以目前我正在考虑放弃这个并使用scrapy和他们自己的代理功能来填写表格。 stackoverflow.com/questions/28852057/…blog.scrapinghub.com/2012/10/26/…
  • 我不推荐使用代理,因为它会滥用并且它可能无论如何都不会工作。谷歌很可能根据 API 密钥设置配额。使用 Bing 地图怎么样?
猜你喜欢
  • 2020-10-30
  • 2023-03-28
  • 2021-01-10
  • 2019-10-22
  • 2011-03-30
  • 1970-01-01
  • 2022-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多