創(chuàng)新互聯(lián)www.cdcxhl.cn八線動態(tài)BGP香港云服務(wù)器提供商,新人活動買多久送多久,劃算不套路!
創(chuàng)新互聯(lián)基于分布式IDC數(shù)據(jù)中心構(gòu)建的平臺為眾多戶提供資陽主機托管 四川大帶寬租用 成都機柜租用 成都服務(wù)器租用。小編給大家分享一下Python源代碼與檢查元素不一致怎么辦,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!
針對源代碼和檢查元素不一致的網(wǎng)頁爬蟲——利用Selenium、PhantomJS、bs4爬取12306的列車途徑站信息
整個程序的核心難點在于上次豆瓣爬蟲針對的是靜態(tài)網(wǎng)頁,源代碼和檢查元素內(nèi)容相同;而在12306的查找搜索過程中,其網(wǎng)頁發(fā)生變化(出現(xiàn)了查找到的數(shù)據(jù)),這個過程是動態(tài)的,使得我們在審查元素中能一一對應(yīng)看到的表格數(shù)據(jù)沒有顯示在源代碼中。這也是這次12306爬蟲和上次豆瓣書單爬蟲的大不同點。
選擇使用Selenium的PhantomJS模擬瀏覽器爬取源代碼,這樣獲取到的datas包含了我需要的(查找搜索出的)途徑站數(shù)據(jù)。
暫時把整個程序分為了這幾個部分:
(1)提取列車Code和No信息;
(2)找到url規(guī)律,根據(jù)Code和No變化實現(xiàn)多個網(wǎng)頁數(shù)據(jù)爬取;
(3)使用PhantomJS模擬瀏覽器爬取源代碼;
(4)用bs4解析源代碼,獲取所需的途徑站數(shù)據(jù);
(5)用csv庫存儲獲得的數(shù)據(jù)。
整體使用面向過程的書寫方式。
(1)values_get()函數(shù)實現(xiàn)了從已有存儲了列車信息的csv中逐次提取Code和No。(在這里有點刻意追求面向過程的函數(shù),設(shè)置了每次提取都o(jì)penfile再close。所以使用了tell一次readline完的游標(biāo)位置,再seek次游標(biāo)位置到下一次提取位置,實現(xiàn)關(guān)閉file后仍然可以接著上一次結(jié)束的seek位置繼續(xù)操作)
(2)olddriver()函數(shù)包含PhantomJS和bs4兩個部分。利用format來控制多個url,用PhantomJS、driver代替requests爬取網(wǎng)頁源代碼driver.get(url)。service_args可以配置模擬瀏覽器(優(yōu)化加速),set_page_load_timeout()和set_script_timeout()+try except('window.stop()')設(shè)置超時(還未用上,存疑),最后用driver.quit()關(guān)閉使用完的PhantomJS避免內(nèi)存爆炸。*這里存在很多優(yōu)化模擬瀏覽器的方法,除了上述的配置、超時、quit,還包括在循環(huán)外提前打開PhantomJS來實現(xiàn)程序運行時間加速等方法,筆者還未理解透這些方法。這里貼出優(yōu)化的參考鏈接:①https://blog.csdn.net/weixin_40284075/article/details/87190040②https://www.jianshu.com/p/8ec70859ae03還有PhantomJS的使用攻略①https://www.cnblogs.com/miqi1992/p/8093958.html②https://www.cnblogs.com/lizm166/p/8360388.html
為什么使用已經(jīng)被Selenium拋棄的PhantomJS而不使用Headless Chrome?筆者也曾嘗試過使用無頭chrome,但爬到的源代碼仍不包含我所需tbody數(shù)據(jù)。
丟失數(shù)據(jù)的源代碼長這樣(它只有tbody標(biāo)簽,沒有標(biāo)簽內(nèi)的數(shù)據(jù))。
而檢查元素里可以看到所需數(shù)據(jù)出現(xiàn)在tbody內(nèi):
雖然用PhantomJS確實可以爬取到所需的tbody數(shù)據(jù),但是在后來循環(huán)url爬取多個列車信息時,可能是因為網(wǎng)站有反爬蟲措施,或是PhantomJS的不穩(wěn)定,導(dǎo)致了經(jīng)常會出現(xiàn)丟失數(shù)據(jù)的情況(PhantomJS的作用失效了)。所以我添加了一句if datas==[],遞歸olddriver()來確保能爬到這班列車的信息。如圖,失敗率仍然很高。
(3)最后是data_write_csv()寫入數(shù)據(jù)到csv,這里用csv庫直接把列表變?yōu)榱薱sv文件(列表中的多個列表就是多行數(shù)據(jù)),以后多嘗試用一下csv庫,還是很好用的。
(4)在主程序調(diào)用各個函數(shù)時,要注意global全局變量的使用、函數(shù)return參數(shù)給其他函數(shù)使用。
(5)最后是幾點自己的建議和猜想。首先如果12306真的有反爬蟲,我們可以嘗試像requests一樣的偽裝(在driver里沒刻意偽裝)或是換其他的網(wǎng)站來爬取。其次多注意:爬取網(wǎng)頁查詢搜索數(shù)據(jù)的方法,網(wǎng)頁跳轉(zhuǎn)等(或簡易成爬取多個網(wǎng)頁數(shù)據(jù),如本例)。還有PhantomJS和headless Chrome,按理來說headless Chrome不會出現(xiàn)這樣的錯誤。最后是提升爬蟲運行速度的方法,(這次的爬取速度實在太慢了,10條信息平均要3分鐘才能成功獲得),除了對模擬瀏覽器的配置和優(yōu)化,以及代碼本身的優(yōu)化(如file文件一直開著,不提取一次數(shù)據(jù)就開關(guān)file一次),我們是否可以嘗試其他的源代碼.get(url)獲取方式?嘗試多線程加速?嘗試云服務(wù)器?
代碼:
import urllib3 #import requests from selenium import webdriver from bs4 import BeautifulSoup import csv import time start = time.time() def values_get():#通過設(shè)置游標(biāo)來實現(xiàn):從上一次結(jié)束的地方繼續(xù)讀取 file = open('Code.csv','r') global seekloc#全局游標(biāo) file.seek(seekloc)#設(shè)置游標(biāo)位置 line = file.readline() ''' if line == '': break ''' if line == '': seekloc = -1 twovalue = line.strip('\n').split(',')#csv轉(zhuǎn)化為list code, no = twovalue[0], twovalue[1] seekloc = file.tell()#讀取結(jié)束時游標(biāo)的位置 file.close() return code, no#code是列車號,no是長串 def olddriver(): #下文中將PhantomJS移除循環(huán)未果,任選擇在循環(huán)中打開。 service_args=[]#PhantomJS優(yōu)化 service_args.append('--load-images=no') ##關(guān)閉圖片加載 driver = webdriver.PhantomJS(service_args=service_args) driver.set_page_load_timeout(10) # 設(shè)置頁面加載超時 driver.set_script_timeout(10) # 設(shè)置頁面異步j(luò)s執(zhí)行超時 url = f'https://kyfw.12306.cn/otn/queryTrainInfo/init?train_no={no}&station_train_code={code}&date=2019-07-16' try: driver.get(url) data = driver.page_source except: print('Timeout!') driver.execute_script('window.stop()') driver.quit()#這句可讓PhantomJS關(guān)閉 #return data #def beauti4soup(): #global data soup = BeautifulSoup(data,'lxml') table_datas = soup.find('table',{'id':'queryTable'}) datas = table_datas.findAll('tbody')[1].findAll('tr') if datas == []: print('Failed... Restart!') olddriver() #beauti4soup() else: print("It's OK! ") midways = [] for data in datas: midway = data.find('div',{'class':'t-station'}).get_text()#單個列車的信息爬取 midways.append(midway) answer.append(midways) return answer def data_write_csv(file_name,datas): file_csv = open(file_name,'w+') #writer = csv.writer(file_csv,delimiter=',',quotechar=' ',quoting=csv.QUOTE_MINIMAL)csv庫用法存疑 writer = csv.writer(file_csv) for data in datas: writer.writerow(data) #---主程序開始---# seekloc = 0#初始化游標(biāo) values_get()#運行一次values_get()把csv無用的第一行過濾掉 answer = []#存儲所有途徑站信息的list ''' #這里三行嘗試將PhantomJS放在循環(huán)外,提前開啟,減少加載時間。 #結(jié)果:運行時間確實大幅減短,但遇到一次failed之后就一直failed。 #參考鏈接:https://blog.csdn.net/qingwuh/article/details/81583801 service_args=[]#PhantomJS優(yōu)化 service_args.append('--load-images=no') ##關(guān)閉圖片加載 driver = webdriver.PhantomJS(service_args=service_args) ''' j = 1 while True:#循環(huán)爬取 code, no = values_get() if j > 10:#十個一循環(huán)的測試 break #if seekloc == -1: # break answer = olddriver() j += 1 data_write_csv('Route.csv',answer)#存儲數(shù)據(jù) #---主程序結(jié)束---# end = time.time() print('Running time: {} Seconds'.format(end-start)) print("=================================")
看完了這篇文章,相信你對Python源代碼與檢查元素不一致怎么辦有了一定的了解,想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道,感謝各位的閱讀!
新聞名稱:Python源代碼與檢查元素不一致怎么辦-創(chuàng)新互聯(lián)
文章網(wǎng)址:http://m.newbst.com/article0/dpeooo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、軟件開發(fā)、關(guān)鍵詞優(yōu)化、域名注冊、營銷型網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容