继续练手,写了一个已知地理位置爬经纬度的代码,用selenium模拟操作浏览器。
编程环境:py3
假定地理位置的读取与写入均在excel中进行
当数据量较大时需要调openpyxl而不是xlwt来写入数据:
import xlrd
from openpyxl import Workbook
from selenium import webdriver
import time
先将所有地理位置读入一个list中:
def get_location(sql_results,exam_num): #获得所有地址
location = []
for i in range(exam_num):
value = sql_results.cell_value(i+2,8)
if value in location:
continue
else:
location.append(value)
return location
查询经纬度使用网站:http://www.gpsspg.com/maps.htm
由于使用的是chrome浏览器,所以先下载了一个ChromeDriver并复制到python3的安装目录中。
selenium提供了很多寻找标签的方法,类似于BeautifulSoup寻找tag,但更为直观简便。
若已知id可以使用find_element_by_id,这帮助我们寻找到文本框(使用.send_keys将文字送入文本框)、按钮(.click()模拟点击按钮)。
也可使用find_element_by_xpath("********").get_attribute("****")获取标签中的其它属性。此例中可通过"style"属性判断地址是否有效,而selenium中并不存在find_element_by_style这样的命令。
考虑到单个地图的局限性,对查询不到的地址会使用另一张地图查询一遍。
def get_xy(location): #获得所有地址的坐标
xy = {}
loca_len = len(location)
browser = webdriver.Chrome()
browser.maximize_window()
browser.implicitly_wait(3)
url = 'http://www.gpsspg.com/maps.htm'
browser.get(url)
map_choice = browser.find_element_by_id("sm_1") #切换地图
map_choice.click()
time.sleep(5)
text = browser.find_element_by_id('s_t') #找到文本框
count = 0 #记录查询有错的地址个数
error_record = []
for element in location:
if location.index(element)%100==99:
time.sleep(60)
print (element)
try:
text.clear()
text.send_keys(element)
button = browser.find_element_by_id("s_btn") #找到点击按钮
button.click()
time.sleep(3)
e = browser.find_element_by_xpath("//*[@id='s_msg']").get_attribute("style")
if e=="visibility: hidden;":
results = browser.find_element_by_id("map_t")
result = results.text
result_list = result.strip().split(' ')
weidu = result_list[1]
jingdu = result_list[2]
xy[element] = [weidu,jingdu]
else:
print ("**位置\""+element+"\"描述有误**")
error_record.append(element)
except:
print ("**位置\""+element+"\"查询异常**") #若查询出现异常,则显示有问题的地址
error_record.append(element)
print ("***********************************")
map_choice = browser.find_element_by_id("sm_3") #切换地图
map_choice.click()
time.sleep(5)
text = browser.find_element_by_id('s_t')
for element in error_record:
try:
text.clear()
text.send_keys(element)
button = browser.find_element_by_id("s_btn") #找到点击按钮
button.click()
time.sleep(3)
e = browser.find_element_by_xpath("//*[@id='s_msg']").get_attribute("style")
if e=="visibility: hidden;":
results = browser.find_element_by_id("map_t")
result = results.text
result_list = result.strip().split(' ')
weidu = result_list[1]
jingdu = result_list[2]
xy[element] = [weidu,jingdu]
else:
count = count+1
print ("**位置\""+element+"\"描述有误**")
xy[element] = ["**\""+element+"\"描述有误**","**\""+element+"\"描述有误**"]
except:
count = count+1
print ("**位置\""+element+"\"查询异常**") #若查询出现异常,则显示有问题的地址
xy[element] = ["**\""+element+"\"查询异常**","**\""+element+"\"查询异常**"]
browser.quit()
return xy,count
然后按照原有的顺序,在dict中找寻地理位置所对应的经纬度,并用openpyxl保存进工作表中。
def add_xy(): #将坐标添加进excel
path = r'F:\test.xlsx'
workbook = xlrd.open_workbook(path)
sql_results = workbook.sheet_by_name('基本数据')
exam_num = sql_results.nrows-2 #获得样本数
location = get_location(sql_results,exam_num)
xy,count = get_xy(location)
print ("共有%d项错误"%count)
workbook_new = Workbook()
sheet_new = workbook_new.active
sheet_new['A1'].value = "纬度"
sheet_new['B1'].value = "经度"
for i in range(exam_num):
t = sql_results.cell_value(i+2,8)
#sheet_new.write(i+1,0,xy[t][0])
#sheet_new.write(i+1,1,xy[t][1])
sheet_new['A%d'%(i+2)].value = xy[t][0]
sheet_new['B%d'%(i+2)].value = xy[t][1]
workbook_new.save("F:\test(经纬度).xls")
最后执行程序:
if __name__=="__main__":
add_xy()