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框架而言,本身自己的特色就是快,写好抓取和解析规则后,无惧这类频繁注册的网站。