溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python源代碼與檢查元素不一致怎么辦

發(fā)布時(shí)間:2020-08-06 13:56:56 來(lái)源:億速云 閱讀:828 作者:小新 欄目:編程語(yǔ)言

小編給大家分享一下Python源代碼與檢查元素不一致怎么辦,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

針對(duì)源代碼和檢查元素不一致的網(wǎng)頁(yè)爬蟲(chóng)——利用Selenium、PhantomJS、bs4爬取12306的列車(chē)途徑站信息

整個(gè)程序的核心難點(diǎn)在于上次豆瓣爬蟲(chóng)針對(duì)的是靜態(tài)網(wǎng)頁(yè),源代碼和檢查元素內(nèi)容相同;而在12306的查找搜索過(guò)程中,其網(wǎng)頁(yè)發(fā)生變化(出現(xiàn)了查找到的數(shù)據(jù)),這個(gè)過(guò)程是動(dòng)態(tài)的,使得我們?cè)趯彶樵刂心芤灰粚?duì)應(yīng)看到的表格數(shù)據(jù)沒(méi)有顯示在源代碼中。這也是這次12306爬蟲(chóng)和上次豆瓣書(shū)單爬蟲(chóng)的最大不同點(diǎn)。

選擇使用Selenium的PhantomJS模擬瀏覽器爬取源代碼,這樣獲取到的datas包含了我需要的(查找搜索出的)途徑站數(shù)據(jù)。

暫時(shí)把整個(gè)程序分為了這幾個(gè)部分:

(1)提取列車(chē)Code和No信息;

(2)找到url規(guī)律,根據(jù)Code和No變化實(shí)現(xiàn)多個(gè)網(wǎng)頁(yè)數(shù)據(jù)爬??;

(3)使用PhantomJS模擬瀏覽器爬取源代碼;

(4)用bs4解析源代碼,獲取所需的途徑站數(shù)據(jù);

(5)用csv庫(kù)存儲(chǔ)獲得的數(shù)據(jù)。

整體使用面向過(guò)程的書(shū)寫(xiě)方式。

(1)values_get()函數(shù)實(shí)現(xiàn)了從已有存儲(chǔ)了列車(chē)信息的csv中逐次提取Code和No。(在這里有點(diǎn)刻意追求面向過(guò)程的函數(shù),設(shè)置了每次提取都o(jì)penfile再close。所以使用了tell一次readline完的游標(biāo)位置,再seek次游標(biāo)位置到下一次提取位置,實(shí)現(xiàn)關(guān)閉file后仍然可以接著上一次結(jié)束的seek位置繼續(xù)操作)

(2)olddriver()函數(shù)包含PhantomJS和bs4兩個(gè)部分。利用format來(lái)控制多個(gè)url,用PhantomJS、driver代替requests爬取網(wǎng)頁(yè)源代碼driver.get(url)。service_args可以配置模擬瀏覽器(優(yōu)化加速),set_page_load_timeout()和set_script_timeout()+try except('window.stop()')設(shè)置超時(shí)(還未用上,存疑),最后用driver.quit()關(guān)閉使用完的PhantomJS避免內(nèi)存爆炸。*這里存在很多優(yōu)化模擬瀏覽器的方法,除了上述的配置、超時(shí)、quit,還包括在循環(huán)外提前打開(kāi)PhantomJS來(lái)實(shí)現(xiàn)程序運(yùn)行時(shí)間加速等方法,筆者還未理解透這些方法。這里貼出優(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?筆者也曾嘗試過(guò)使用無(wú)頭chrome,但爬到的源代碼仍不包含我所需tbody數(shù)據(jù)。

丟失數(shù)據(jù)的源代碼長(zhǎng)這樣(它只有tbody標(biāo)簽,沒(méi)有標(biāo)簽內(nèi)的數(shù)據(jù))。

Python源代碼與檢查元素不一致怎么辦

而檢查元素里可以看到所需數(shù)據(jù)出現(xiàn)在tbody內(nèi):

Python源代碼與檢查元素不一致怎么辦

雖然用PhantomJS確實(shí)可以爬取到所需的tbody數(shù)據(jù),但是在后來(lái)循環(huán)url爬取多個(gè)列車(chē)信息時(shí),可能是因?yàn)榫W(wǎng)站有反爬蟲(chóng)措施,或是PhantomJS的不穩(wěn)定,導(dǎo)致了經(jīng)常會(huì)出現(xiàn)丟失數(shù)據(jù)的情況(PhantomJS的作用失效了)。所以我添加了一句if datas==[],遞歸olddriver()來(lái)確保能爬到這班列車(chē)的信息。如圖,失敗率仍然很高。

Python源代碼與檢查元素不一致怎么辦

(3)最后是data_write_csv()寫(xiě)入數(shù)據(jù)到csv,這里用csv庫(kù)直接把列表變?yōu)榱薱sv文件(列表中的多個(gè)列表就是多行數(shù)據(jù)),以后多嘗試用一下csv庫(kù),還是很好用的。

(4)在主程序調(diào)用各個(gè)函數(shù)時(shí),要注意global全局變量的使用、函數(shù)return參數(shù)給其他函數(shù)使用。

(5)最后是幾點(diǎn)自己的建議和猜想。首先如果12306真的有反爬蟲(chóng),我們可以嘗試像requests一樣的偽裝(在driver里沒(méi)刻意偽裝)或是換其他的網(wǎng)站來(lái)爬取。其次多注意:爬取網(wǎng)頁(yè)查詢(xún)搜索數(shù)據(jù)的方法,網(wǎng)頁(yè)跳轉(zhuǎn)等(或簡(jiǎn)易成爬取多個(gè)網(wǎng)頁(yè)數(shù)據(jù),如本例)。還有PhantomJS和headless Chrome,按理來(lái)說(shuō)headless Chrome不會(huì)出現(xiàn)這樣的錯(cuò)誤。最后是提升爬蟲(chóng)運(yùn)行速度的方法,(這次的爬取速度實(shí)在太慢了,10條信息平均要3分鐘才能成功獲得),除了對(duì)模擬瀏覽器的配置和優(yōu)化,以及代碼本身的優(yōu)化(如file文件一直開(kāi)著,不提取一次數(shù)據(jù)就開(kāi)關(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():#通過(guò)設(shè)置游標(biāo)來(lái)實(shí)現(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é)束時(shí)游標(biāo)的位置
      file.close()
      return code, no#code是列車(chē)號(hào),no是長(zhǎng)串
  
  def olddriver():
  
      #下文中將PhantomJS移除循環(huán)未果,任選擇在循環(huán)中打開(kāi)。
      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è)置頁(yè)面加載超時(shí)
      driver.set_script_timeout(10)  # 設(shè)置頁(yè)面異步j(luò)s執(zhí)行超時(shí)
      
      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()#單個(gè)列車(chē)的信息爬取
          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庫(kù)用法存疑
      writer = csv.writer(file_csv)
      for data in datas:
          writer.writerow(data)
  
  
  #---主程序開(kāi)始---#
  
  seekloc = 0#初始化游標(biāo)
  values_get()#運(yùn)行一次values_get()把csv無(wú)用的第一行過(guò)濾掉
  answer = []#存儲(chǔ)所有途徑站信息的list
  '''
  #這里三行嘗試將PhantomJS放在循環(huán)外,提前開(kāi)啟,減少加載時(shí)間。
  #結(jié)果:運(yùn)行時(shí)間確實(shí)大幅減短,但遇到一次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:#十個(gè)一循環(huán)的測(cè)試
          break
      #if seekloc == -1:
      #    break
      answer = olddriver()
      j += 1 
  
  data_write_csv('Route.csv',answer)#存儲(chǔ)數(shù)據(jù) 
  
  #---主程序結(jié)束---#
  end = time.time()
   print('Running time: {} Seconds'.format(end-start))
   print("=================================")

看完了這篇文章,相信你對(duì)Python源代碼與檢查元素不一致怎么辦有了一定的了解,想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI