[python爬蟲] selenium爬取區域性動態重新整理網站(URL始終固定)

Eastmount發表於2018-04-26

在爬取網站過程中,通常會遇到區域性動態重新整理情況,當你點選“下一頁”或某一頁時,它的資料就進行重新整理,但其頂部的URL始終不變。這種區域性動態重新整理的網站,怎麼爬取資料呢?某網站資料顯示如下圖所示,當點選“第五頁”之時,其URL始終不變,傳統的網站爬取方法是無法拼接這類連結的,所以本篇文章主要解決這個問題。


本文主要採用Selenium爬取區域性動態重新整理的網站,獲取“下一頁”按鈕實現自動點選跳轉,再依次爬取每一頁的內容。希望對您有所幫助,尤其是遇到同樣問題的同學,如果文章中出現錯誤或不足之處,還請海涵~




一. Selenium爬取第一頁資訊

首先,我們嘗試使用Selenium爬取第一頁的內容,採用瀏覽器右鍵“審查”元素,可以看到對應的HTML原始碼,如下圖所示,可以看到,每一行工程資訊都位於<table class="table table-hover">節點下的<tr>...</tr>中。


然後我們再展開其中一個<tr>...</tr>節點,看它的原始碼詳情,如下圖所示,包括公告標題、釋出時間、專案所在地。如果我們需要抓取公告標題,則定位<div class="div_title text_view">節點,再獲取標題內容和超連結。

完整程式碼如下:

# coding=utf-8    
from selenium import webdriver    
import re
import time
import os

print "start"
#開啟Firefox瀏覽器 設定等待載入時間
driver = webdriver.Firefox()

#定位節點
url = 'http:/www.xxxx.com/'
print url
driver.get(url)
content = driver.find_elements_by_xpath("//div[@class='div_title text_view']")
for u in content:
    print u.text

輸出內容如下圖所示:



PS:由於網站安全問題,我不直接給出網址,主要給出爬蟲的核心思想。同時,下面的程式碼我也沒有給出網址,但思路一樣,請大家替換成自己的區域性重新整理網址進行測試。



二. Selenium實現區域性動態重新整理爬取

接下來我們想爬取第2頁的網站內容,其程式碼步驟如下:
    1.定位驅動:driver = webdriver.Firefox()
    2.訪問網址:driver.get(url)
    3.定位節點獲取第一頁內容並爬取:driver.find_elements_by_xpath()
    4.獲取“下一頁”按鈕,並呼叫click()函式點選跳轉
    5.爬取第2頁的網站內容:driver.find_elements_by_xpath()

其核心步驟是獲取“下一頁”按鈕,並呼叫Selenium自動點選按鈕技術,從而實現跳轉,之後再爬取第2頁內容。“下一頁”按鈕的原始碼如下圖所示:


其中,“下一頁”按鈕始終在第9個<li>...</li>位置,則核心程式碼如下:
nextPage = driver.find_element_by_xpath("//ul[@class='pagination']/li[9]/a")
nextPage.click()


完整程式碼如下:

# coding=utf-8    
from selenium import webdriver    
import re
import time
import os

print "start"
driver = webdriver.Firefox()

url = 'http://www.XXXX.com/'
print url
driver.get(url)
#專案名稱
titles = driver.find_elements_by_xpath("//div[@class='div_title text_view']")
for u in titles:
    print u.text
#超連結
urls = driver.find_elements_by_xpath("//div[@class='div_title text_view']/a")
for u in urls:
    print u.get_attribute("href")
#時間
times = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[2]")
for u in times:
    print u.text
#地點
places = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[3]")
for u in places:
    print u.text


#點選下一頁
nextPage = driver.find_element_by_xpath("//ul[@class='pagination']/li[9]/a")
print nextPage.text
nextPage.click()
time.sleep(5)

#爬取第2頁資料
content = driver.find_elements_by_xpath("//div[@class='div_title text_view']")
for u in content:
    print u.text
輸出內容如下所示,可以看到第二頁的內容也爬取成功了,並且作者爬取了公告主題、超連結、釋出時間、釋出地點。
>>> 
start
http://www.xxxx.com/
觀山湖區依法治國普法教育基地(施工)中標候選人公示
興義市2017年農村公路生命防護工程一期招標公告
安龍縣市政廣場地下停車場10kV線路遷改、10kV臨時用電、10kV電纜敷設及400V電纜敷設工程施工公開競爭性談判公告
劍河縣小香雞種苗孵化場建設專案(場坪工程)中標公示
安龍縣棲鳳生態溼地走廊建設專案(原冰河步道A、B段)10kV線路、400V線路、220V線路及變壓器遷改工程施工招標
鎮寧自治縣2017年簡嘎鄉農村飲水安全鞏固提升工程(施工)招標廢標公示
S313線安龍縣城至普坪段道路改擴建工程勘察招標公告
S313線安龍縣城至普坪段道路改擴建工程勘察招標公告
貴州中煙工業有限責任公司2018物資公開招標-捲菸紙中標候選人公示
冊亨縣者樓河納福新區河段生態治理專案(上游一標段)初步設計 招標公告
http://www.gzzbw.cn/historydata/view/?id=116163
http://www.gzzbw.cn/historydata/view/?id=114995
http://www.gzzbw.cn/historydata/view/?id=115720
http://www.gzzbw.cn/historydata/view/?id=116006
http://www.gzzbw.cn/historydata/view/?id=115719
http://www.gzzbw.cn/historydata/view/?id=115643
http://www.gzzbw.cn/historydata/view/?id=114966
http://www.gzzbw.cn/historydata/view/?id=114965
http://www.gzzbw.cn/historydata/view/?id=115400
http://www.gzzbw.cn/historydata/view/?id=116031
2017-12-22
2017-12-22
2017-12-22
2017-12-22
2017-12-22
2017-12-22
2017-12-22
2017-12-22
2017-12-22
2017-12-22
未知
興義市
安龍縣
未知
安龍縣
未知
安龍縣
安龍縣
未知
冊亨縣
下一頁
冊亨縣丫他鎮板其村埃近1~2組村莊綜合整治專案
冊亨縣者樓河納福新區河段生態治理專案(上游一標段)勘察 招標公告
惠水縣撤併建制村通硬化路施工總承包中標候選人公示
冊亨縣丫他鎮板街村村莊綜合整治專案施工招標 招標公告
鎮寧自治縣農村環境整治工程專案(環翠街道辦事處)施工(三標段)(二次)(專案名稱)交易結果公示
丫他鎮生態移民附屬設施建設專案
劍河縣城市管理辦公室的劍河縣仰阿莎主題文化廣場護坡綠化工程中標公示
冊亨縣者樓河納福新區河段生態治理專案(上游一標段)施工圖設計
冊亨縣2017年巖架城市棚戶區改造專案配套基礎設施建設專案 中標公示
數字甕安地理空間框架建設專案
>>> 
Firefox成功跳轉到第2頁,此時你增加一個迴圈則可以跳轉很多頁,並爬取資訊,詳見第三個步驟。



三. Selenium爬取詳情頁面

上面爬取了每行公告資訊的詳情頁面超連結(URL),本來我準備採用BeautifulSoup爬蟲爬取詳情頁面資訊的,但是被攔截了,詳情頁面如下圖所示:

這裡作者繼續定義另一個Selenium Firefox驅動進行爬取,完整程式碼如下:
# coding=utf-8    
from selenium import webdriver    
from selenium.webdriver.common.keys import Keys            
import re
import time
import os

print "start"
#開啟Firefox瀏覽器 
driver = webdriver.Firefox()
driver2 = webdriver.Firefox()

url = 'http://www.xxxx.com/'
print url
driver.get(url)
#專案名稱
titles = driver.find_elements_by_xpath("//div[@class='div_title text_view']")
#超連結
urls = driver.find_elements_by_xpath("//div[@class='div_title text_view']/a")
num = []
for u in urls:
    href = u.get_attribute("href")
    driver2.get(href)
    con = driver2.find_element_by_xpath("//div[@class='col-xs-9']") 
    #print con.text
    num.append(con.text)
#時間
times = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[2]")
#地點
places = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[3]")

#輸出所有結果
print len(num)
i = 0
while i<len(num):
    print titles[i].text
    print urls[i].get_attribute("href")
    print times[i].text
    print places[i].text
    print num[i]
    print ""
    i = i + 1


#點選下一頁
j = 0
while j<5:
    nextPage = driver.find_element_by_xpath("//ul[@class='pagination']/li[9]/a")
    print nextPage.text
    nextPage.click()
    time.sleep(5)

    #專案名稱
    titles = driver.find_elements_by_xpath("//div[@class='div_title text_view']")
    #超連結
    urls = driver.find_elements_by_xpath("//div[@class='div_title text_view']/a")
    num = []
    for u in urls:
        href = u.get_attribute("href")
        driver2.get(href)
        con = driver2.find_element_by_xpath("//div[@class='col-xs-9']") 
        num.append(con.text)
    #時間
    times = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[2]")
    #地點
    places = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[3]")
    #輸出所有結果
    print len(num)
    i = 0
    while i<len(num):
        print titles[i].text
        print urls[i].get_attribute("href")
        print times[i].text
        print places[i].text
        print num[i]
        print ""
        i = i + 1

    j = j + 1

注意作者定義了一個while迴圈,一次性輸出一條完整的招標資訊,程式碼如下:

print len(num)
i = 0
while i<len(num):
    print titles[i].text
    print urls[i].get_attribute("href")
    print times[i].text
    print places[i].text
    print num[i]
    print ""
    i = i + 1

輸出結果如下圖所示:


其中一條完整的結果如下所示:

觀山湖區依法治國普法教育基地(施工)中標候選人公示
http://www.gzzbw.cn/historydata/view/?id=116163
2017-12-22
未知
觀山湖區依法治國普法教育基地(施工)中標候選人公示
來源: 貴州百利工程建設諮詢有限公司 釋出時間: 2017-12-22
根據法律、法規、規章和招標檔案的規定,觀山湖區司法局、貴陽觀山湖投資(集團)旅遊文化產業發展有限公司(代建)的觀山湖區依法治國普法
教育基地(施工)(專案編號:BLZB01201744) 已於2017年 12月22日進行談判,根據談判小組出具的競爭性談判報告,現公示下列內容:
 第一中標候選人:貴州鴻友誠建築安裝有限公司
中標價:1930000.00(元)       工  期:57日曆天
 第二中標候選人:貴州隆瑞建設有限公司
中標價:1940000.00(元)       工  期:60日曆天
 第三中標候選人:鳳岡縣建築工程有限責任總公司
中標價:1953285.00(元)       工  期:60日曆天
 中標結果公示至2017年12月25日。
                      招  標  人:貴陽觀山湖投資(集團)有限公司
                     招標代理人:貴州百利工程建設諮詢有限公司  
                                  2017年12月22日
最後讀者可以結合MySQLdb庫,將爬取的內容儲存至本地中。同時,如果您爬取的內容需要設定時間,比如2015年的資料,則在爬蟲開始之前設定time.sleep(5)暫定函式,手動點選2015年或輸入關鍵字,再進行爬取。也建議讀者採用Selenium技術來自動跳轉,而詳情頁面採用BeautifulSoup爬取。

# coding=utf-8    
from selenium import webdriver    
from selenium.webdriver.common.keys import Keys    
import selenium.webdriver.support.ui as ui         
import re
import time
import os
import codecs
from bs4 import BeautifulSoup
import urllib
import MySQLdb


#儲存資料庫  
#引數:公告名稱 釋出時間 釋出地點 釋出內容  
def DatabaseInfo(title,url,fbtime,fbplace,content):    
    try:    
        conn = MySQLdb.connect(host='localhost',user='root',  
                             passwd='123456',port=3306, db='20180426ztb')    
        cur=conn.cursor() #資料庫遊標    
    
        #報錯:UnicodeEncodeError: 'latin-1' codec can't encode character    
        conn.set_character_set('utf8')    
        cur.execute('SET NAMES utf8;')    
        cur.execute('SET CHARACTER SET utf8;')    
        cur.execute('SET character_set_connection=utf8;')  
  
        #SQL語句 智聯招聘(zlzp)  
        sql = '''insert into ztb  
                    (title, url, fbtime, fbplace, content)  
                values(%s, %s, %s, %s, %s);'''
        cur.execute(sql, (title,url,fbtime,fbplace,content))  
        print '資料庫插入成功'              
          
    #異常處理    
    except MySQLdb.Error,e:    
        print "Mysql Error %d: %s" % (e.args[0], e.args[1])    
    finally:    
        cur.close()      
        conn.commit()      
        conn.close()

        
print "start"
#開啟Firefox瀏覽器 
driver = webdriver.Firefox()
driver2 = webdriver.Firefox()

url = 'http://www.gzzbw.cn/historydata/'
print url
driver.get(url)
#專案名稱
titles = driver.find_elements_by_xpath("//div[@class='div_title text_view']")
#超連結
urls = driver.find_elements_by_xpath("//div[@class='div_title text_view']/a")
num = []
for u in urls:
    href = u.get_attribute("href")
    driver2.get(href)
    con = driver2.find_element_by_xpath("//div[@class='col-xs-9']") 
    #print con.text
    num.append(con.text)
#時間
times = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[2]")
#地點
places = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[3]")

#輸出所有結果
print len(num)
i = 0
while i<len(num):
    print titles[i].text
    print urls[i].get_attribute("href")
    print times[i].text
    print places[i].text
    print num[i]
    print ""
    DatabaseInfo(titles[i].text, urls[i].get_attribute("href"), times[i].text,
                 places[i].text, num[i])
    i = i + 1


#點選下一頁
j = 0
while j<100:
    nextPage = driver.find_element_by_xpath("//ul[@class='pagination']/li[9]/a")
    print nextPage.text
    nextPage.click()
    time.sleep(5)

    #專案名稱
    titles = driver.find_elements_by_xpath("//div[@class='div_title text_view']")
    #超連結
    urls = driver.find_elements_by_xpath("//div[@class='div_title text_view']/a")
    num = []
    for u in urls:
        href = u.get_attribute("href")
        driver2.get(href)
        con = driver2.find_element_by_xpath("//div[@class='col-xs-9']") 
        num.append(con.text)
    #時間
    times = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[2]")
    #地點
    places = driver.find_elements_by_xpath("//table[@class='table table-hover']/tbody/tr/td[3]")
    #輸出所有結果
    print len(num)
    i = 0
    while i<len(num):
        print titles[i].text
        print urls[i].get_attribute("href")
        print times[i].text
        print places[i].text
        print num[i]
        print ""
        DatabaseInfo(titles[i].text, urls[i].get_attribute("href"), times[i].text,
                 places[i].text, num[i])
        i = i + 1

    print u"已爬取頁碼:", (j+2)
    j = j + 1
儲存至資料庫:

最後希望文章對您有所幫助,尤其是要爬取區域性重新整理的同學,
如果文章中出現錯誤或不足之處,還請海涵~

(By:Eastmount 2018-04-26 早上11點半 http://blog.csdn.net/eastmount/ )


相關文章