github地址: github.com/jiahaoabc/c…
思科是一家世界500強企業,尤爲在通信領域是頂尖的存在,它是全球領先的互聯網解決方案供應商,提供了企業網絡、數據中心、安全協做以及物聯網(loT)等解決方案。在思科的官網提供了關於交換機、路由器、無線和有線網絡或其餘的一些產品的產品手冊、白皮書、產品簡介、設計指南、解決方案等等文件。html
本文的目的是抓取上述文件,將這些文件的標題、大小、所在url以及文件自己存入MongoDB數據庫。python
通常而言,咱們要抓取的數據沒必要要從一個網站的首頁開始,定位到數據存在的子頁面直接抓取會更加方便,思科官網是英文的不方便咱們分析,轉換爲中文頁面,而後對官網層層嵌入查找,找到咱們須要的抓取的企業網絡資料頁以下圖所示,而後抓取交換機、路由器、無線、網絡以及其它這些標籤下的全部pdf文件(全部文件均爲pdf格式存在)git
整體分析了一下這個網站和這些文件的加載方式,數據量不大,難度也通常吧,不過有兩個和其餘網站不一樣的並且挺有意思的點。原本覺得像其餘網站的的pdf文件同樣,只要找到每一個文件的URL點擊便會下載到本地,就能夠直接抓取下來保存。可是每次點擊一個pdf文件,都跳轉到一個不一樣URL的註冊頁面。
github
輸入註冊信息後,點擊下載白皮書,而後又跳到了以下的一個頁面,須要再次點擊下載,最後在此頁面裏點擊下載才能獲得須要的pdf文件。
mongodb
因此,一個有意思的點就在於這個網站每次須要下載一個pdf文件時都須要註冊一次,並且每次註冊的頁面URL都不一樣,不像別的網站註冊登陸後就一勞永逸了。數據庫
另一個有意思的點在於註冊完點擊下載後,不是直接將pdf文件下載下來,而是又跳到一個新的下載頁面,在以前頁面的頁面控制檯下也找不到和這個URL相關的信息,這個URL和pdf文件的URL彷佛也沒有半毛錢關係,由於不提供登陸方法,沒法維持本身客戶機與思科服務器之間的鏈接,因此當再次訪問上面的下載頁面連接‘s177775138.t.eloqua.com/e/f2’時直接報錯。安全
用框架pyspider和pycharm寫了兩份代碼,這裏就講一下pyspider的實現方式。服務器
首先爬蟲從pdf分佈的列表頁開始進入:網絡
@every (minutes=24 * 60)
def on_start(self):
self.crawl ('https://www.cisco.com/c/m/zh_cn/about/solutions/enterprise-networks/index.html',
callback=self.index_page, validate_cert=False)複製代碼
進入列表頁後開始解析出每一個pdf文件的url,同時提取出每一個url裏的oid值(爲何要取這個,後面說),解析出來後,將oid值回調給login函數進行註冊框架
@config (age=10 * 24 * 60 * 60)
def index_page(self, response):
# 解析頁面全部pdf文件url,獲取每一個url對應的oid值並返回給註冊函數login()
for each in response.doc ('td > a').items ():
#用正則提取兩種不一樣url的oid值
result_one = re.findall (".*en/(.*).html.*", each.attr.href)
result_two = re.findall (".*vertical/(.*).html.*", each.attr.href)
if (result_one):
self.crawl (each.attr.href, callback=self.login, save={'a': result_one}, validate_cert=False)
oid = result_one
elif (result_two):
self.crawl (each.attr.href, callback=self.login, save={'a': result_two}, validate_cert=False)
oid = result_two複製代碼
當執行此函數時,咱們能夠看到一共有140個pdf的url解析出來了(數量和實際數量同樣)
抓取到url後,就像咱們以前分析的那樣,點擊pdf文件,而後就跳轉到一個註冊頁面,此時須要開始post表單進行註冊,經過抓包分析,發現post表單有不少字段,不肯定cisio服務器是對哪些字段進行檢測,因此把全部字段都加入進去是最保險的,其中有一個變化的字段—oid,發現是隱藏在pdf的url中。仔細分析,雖然每次的註冊頁面不一樣,可是隻須要對‘s177775138.t.eloqua.com/e/f2’這個URL進行post提交表單便可完成註冊,而後跳轉到下載頁面,代碼以下:
def login(self, response):
# post註冊登陸,登陸後的頁面返回給detail_page處理
url = response.url
Oid = response.save[ 'a' ]
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36',
'Host': 's177775138.t.eloqua.com', 'Origin': 'https://www.cisco.com', }
post_data = {
'elqFormName': 'GRSDynamicOfferForm',
'elqSiteId': '177775138',
'elqCampaignId': '',
'lastName': '莫嘆',
'emailAddress': '*******',
'busPhone': '********',
'company': 'juejin',
'dropdownMenu': '北京',
'jobLevel1': 'CXO/Executive',
'department': 'MIS/IT - Applications Dev',
'dropdownMenu2': 'Chemical & Petroleum',
'opt_in': 'on',
'updatedby': 'Form - submit',
'emailName': '',
'FORMID': '3473',
'hiddenField3': '',
'hiddenField5': '177775138',
'CCID': 'cc000069',
'DTID': 'odicdc000510',
'OID': Oid, #這個時變化的,須要填入pdf的url裏的oid值
'ECID': '3495',
'keycode1': '',
'GCLID': '', 'keywords': '',
'campaign': '', 'countrySite': '', 'creative': '', 'position': '', 'placement': '', 'referingSite': '',
'search': '', 'hiddenField': '', 'hiddenField2': 'CHINA', 'offerName': '', 'offerSize': '', 'offerURL': '',
'offerURL1': ''}
self.crawl ('https://s177775138.t.eloqua.com/e/f2', callback=self.detail_page, save={'i': Oid}, method='POST',
data=post_data, headers=headers, validate_cert=False)複製代碼
最後,到了下載頁面,對pdf文件的大小、標題、內容進行解析,基本字段信息存入mongodb數據庫,pdf文件存入本地文件夾。
@config (priority=2)
def detail_page(self, response):
# 解析每一個pdf對應的標題、大小、和url存入mongodb,將pdf下載到本地
i = response.save[ 'i' ]
#標題
title = response.doc ('.asset-desc').text ()
#大小
size = response.doc ('.asset-info').text ()
#pdf所在url
pdf_url = response.doc ('.download-button').attr.href
#pdf內容
content = requests.get (pdf_url).content
item = {}
item[ "pdf_title" ] = title
item[ "pdf_size" ] = size
item[ "pdf_url" ] = pdf_url
# pdf_file_path = os.path.abspath ('') + str (i) + '.pdf'
pdf_file_path = 'E:\cisio_demo\cisio_pdf\%s.pdf'%str(i)
print(pdf_file_path)
with open (pdf_file_path, 'wb') as f:
f.write (content)
print(item)
client = pymongo.MongoClient (host='localhost', port=27017)
db = client.test
collection = db.cisco_pyspider
collection.insert (item)複製代碼
pyspider輸出信息以下:
最後,咱們看下pyspider的抓取進程和抓取內容
能夠看出,pyspider這個框架仍是挺好用的,三個函數,幾十行代碼便可抓取到思科官網的資料,雖然須要頻繁註冊,但這對於分佈式的pyspider框架而言,本身自己的特色就是快,寫好抓取和解析規則後,無懼這類頻繁註冊的網站。