记一次Selenium框架的爬虫遇到下拉框页面的解决经历
背景
最近有一個(gè)項(xiàng)目需要使用爬蟲從某網(wǎng)站抓取全國(guó)的醫(yī)院名稱,等級(jí),地址等信息
爬取的url為https://some/website/that/i/can/tell/you/sorry
用瀏覽器打開這個(gè)url會(huì)發(fā)現(xiàn),切換不同的省市需要點(diǎn)擊左上角的下拉框進(jìn)行選擇
問題
通常遇到這種下拉框頁(yè)面,我們第一時(shí)間想到使用Selenium框架的Select類,這個(gè)類是Selenium框架專門用于處理頁(yè)面下拉框的,使用方式如下:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Selectdriver=webdriver.Chrome() #初始化瀏覽器驅(qū)動(dòng)url='https://some/website/that/i/can/tell/you/sorry'#頁(yè)面url driver.get(url)#訪問相對(duì)應(yīng)鏈接 windows_start=driver.window_handles[0] #文檔列表窗口名#定位省市 ele=driver.find_element(By.XPATH,'//*[@id="Prov"]') select_ele = Select(ele) select_ele.select_by_visible_text("北京市") time.sleep(1)#輸入醫(yī)院名稱 driver.find_element(By.XPATH,'//*[@id="Unit_Name"]').send_keys('協(xié)和醫(yī)院')但是Select類只能用于下拉框?qū)崿F(xiàn)方式是基于html的select標(biāo)簽的情況,針對(duì)本項(xiàng)目,打開頁(yè)面源碼發(fā)現(xiàn)
該頁(yè)面的下拉框使用的是input標(biāo)簽!!!!
不慌!
既然不能用Select類一步到位,那我們就老老實(shí)實(shí)的模擬鼠標(biāo)點(diǎn)擊等操作來實(shí)現(xiàn)爬取頁(yè)面過程的省市切換,找到Xpath,調(diào)用click()方法,簡(jiǎn)直不要太簡(jiǎn)單,呵呵呵
但是:
報(bào)錯(cuò)信息no such element,意思是說找不到這個(gè)元素
經(jīng)過不斷的排查發(fā)現(xiàn)這么一個(gè)現(xiàn)象:
第一次打開的時(shí)候下拉框的Xpath:
//*[@id="cascader-menu-7056-0-0"]/span/div
第二次打開的時(shí)候下拉框的Xpath:
//*[@id="cascader-menu-3644-0-0"]/span/div
下拉框的Xpath每次打開頁(yè)面是變化著的,也就是說開發(fā)這個(gè)頁(yè)面的前端工程師還是做了一點(diǎn)反爬措施的,每次點(diǎn)開頁(yè)面以后下拉框的id可能是隨機(jī)生成的,這可如何是好?
不慌!
解決思路
既然每次打開頁(yè)面的時(shí)候Xpath是變化著的,主要是Xpath中間有個(gè)四位數(shù)的隨機(jī)數(shù)
第一次打開的時(shí)候下拉框的Xpath:
//*[@id="cascader-menu-7056-0-0"]/span/div
第二次打開的時(shí)候下拉框的Xpath:
//*[@id="cascader-menu-3644-0-0"]/span/div
我們不去管隨機(jī)數(shù),只關(guān)心當(dāng)前頁(yè)面,想辦法拿到當(dāng)前頁(yè)面的源碼,再?gòu)闹薪馕龀鱿吕虻腦path,在模
擬點(diǎn)擊,則問題就迎刃而解!
基于這個(gè)思路,我們不必關(guān)心每次生成的隨機(jī)數(shù)具體是什么,早知道它是四位數(shù),而且前面為//*[@id="cascader-menu-,后面為-0-0"]/span/div,那么使用正則表達(dá)式來解析簡(jiǎn)直不要太簡(jiǎn)單!
正則表達(dá)式如下:
#獲取隨機(jī)的ID bs = BeautifulSoup(driver.page_source, "html.parser") #解析頁(yè)面源碼 xpath_id = re.findall(r'cascader-menu-[0-9]+-[0-9].*city-select-component-span',driver.page_source)[0] xpath_id = re.findall(r'cascader-menu-[0-9]+-[0-9]+', xpath_id)[0]xpath_id = re.findall(r'\d+', xpath_id)[0]完整代碼
def change_province(driver, province_id):"""點(diǎn)擊下拉框切換特定省市"""#點(diǎn)擊下拉框driver.find_element(By.XPATH,'//*[@id="app_main"]/div/form/div[1]/div/div/div/input').click()time.sleep(1)#獲取隨機(jī)的IDbs = BeautifulSoup(driver.page_source, "html.parser")xpath_id = re.findall(r'cascader-menu-[0-9]+-[0-9].*city-select-component-span',driver.page_source)[0]xpath_id = re.findall(r'cascader-menu-[0-9]+-[0-9]+', xpath_id)[0]xpath_id = re.findall(r'\d+', xpath_id)[0]# 點(diǎn)擊切換固定id的省市driver.find_element(By.XPATH, '//*[@id="cascader-menu-{0}-0-{1}"]/span/div'.format(xpath_id, province_id)).click()time.sleep(np.random.randint(1, 3))def next_page(driver):"""點(diǎn)擊切換下一頁(yè)"""driver.find_element(By.XPATH,'//*[@id="app_main"]/div/div[2]/div/button[2]/i').click()time.sleep(np.random.randint(1,3))def get_info(driver):"""解析信息"""info_list=[]for i in range(1,11):try:info=driver.find_element(By.XPATH,'//*[@id="app_main"]/div/section/div[2]/div[3]/table/tbody/tr[{}]'.format(i)).text info=info.split('\n')info_list.append(info)except Exception as e:breakreturn info_listdriver=webdriver.Chrome() ocr = ddddocr.DdddOcr()url='https://some/website/that/i/can/tell/you/sorry'#打開url driver.get(url)#訪問相對(duì)應(yīng)鏈接 windows_start=driver.window_handles[0] #文檔列表窗口名for province_id in range(0,32):change_province(driver,province_id) #順序切換省市max_page=driver.find_element(By.XPATH,'//*[@id="app_main"]/div/div[2]/div/ul/li[6]').text #獲取最大頁(yè)數(shù)max_page=int(max_page) data=get_info(driver) #獲取第一頁(yè)的數(shù)據(jù)for i in range(0,max_page-1):next_page(driver)data_1=get_info(driver)data.extend(data_1)df_temp=pd.DataFrame(data,columns=['序號(hào)','醫(yī)療機(jī)構(gòu)名稱','醫(yī)療機(jī)構(gòu)類型','醫(yī)療機(jī)構(gòu)等級(jí)','詳細(xì)地址','開通情況'])df_temp.to_excel("./{}.xlsx".format(province_id))總結(jié)
以上是生活随笔為你收集整理的记一次Selenium框架的爬虫遇到下拉框页面的解决经历的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解Nginx:java业务逻辑层都
- 下一篇: Word如何设置单元格垂直居中