介绍
介绍
昨天我们明白了网页蜘蛛的工作原理,今天就可以开始根据这个原理进行代码的编写了。
虽然python也可以编写面向过程的程序,但是使用面向对象的方式编写程序是一个好的习惯,它更加可以满足各种复杂的业务逻辑的需要,同时代码也更容易读懂。
福哥要先开发网页蜘蛛程序,所以先建立一个Spider对象,用它来实现网页蜘蛛的全部功能。
Spider对象
首先,福哥先祭出Spider对象,这个对象就是网页蜘蛛这个对象的抽象类了。这个对象要实现网页蜘蛛的全部功能(当然仅仅是我们需要的功能),里面包含了建立爬取任务队列、爬取网页内容、分析网页内容、保存增量网页等等功能。
代码
这是Spider对象的代码(未完成),保存在 lib/Spider.py 里面,作为一个自定义的软件包使用。
import pymysql from selenium import webdriver import time import re class Spider: mysqlCN = None mysqlCS = None chrome = None chromeOpts = webdriver.ChromeOptions() # chromeOpts.add_argument("--headless") chromeOpts.add_argument("--disable-gpu") chromeOpts.add_argument("--no-sandbox") chrome = webdriver.Chrome(options=chromeOpts) # open mysql def open(self): try: self.mysqlCN = pymysql.connect("192.168.2.168", "tfse", "abcdef") self.mysqlCS = self.mysqlCN.cursor() self.mysqlCN.select_db("tfse") except Exception as e: print(e) exit() # get pending domains def getPendingDomains(self, nums): try: self.mysqlCS.execute("SELECT * FROM websites ORDER BY nextFetchDT ASC, lastFetchDT DESC LIMIT " + str(nums)) rows = self.mysqlCS.fetchall() return rows except Exception as e: print(e) self.mysqlCN.rollback() return None # fetch a domain URL def fetchDomainURL(self, domainName): # open page of domain url = "http://www." + domainName print("打开网址:" + url) self.chrome.get(url) # find all a tags links = self.chrome.find_elements_by_tag_name("a") for link in links: myHref = link.get_attribute("href") if self.isWebPage(myHref, domainName): self.saveWebPage(myHref) else: self.saveDomainPage(myHref) def isWebPage(self, url, domainName): return True def saveWebPage(self, url): print("WebPage: " + url) def saveDomainPage(self, url): print("DomainPage: " + url) # close def close(self): try: self.mysqlCS.close() self.mysqlCN.close() except Exception as e: print(e) exit()
主程序
这里给出蜘蛛的主程序,主程序通过上面的Spider对象实现爬取网页的功能,保存在 Spider.py 里面。
from lib.Spider import * mySpider = Spider() mySpider.open() domains = mySpider.getPendingDomains(10) for domain in domains: mySpider.fetchDomainURL(domain[1]) mySpider.close()
讲解
下面福哥来讲解一下这个代码的逻辑,大家可以跟着福哥的思路一起读这段代码,了解其中的设计和功能。
主程序
主程序首先是通过from和import将Spider软件包里的对象导入进来了。
接着初始化Spider对象到mySpider变量里面。
通过Spider对象的open方法建立MySQL数据库的连接以及初始化工作。
使用Spider对象的getPendingDomains方法从MySQL数据库里查询出10个待处理的域名。
通过for循环对10个域名逐个进行单独的处理,使用Spider对象的fetchDomainURL方法对单独的一个域名进行爬取操作
最后使用Spider对象的close方法关闭MySQL数据库的连接。
Spider对象
接着福哥来对Spider对象的每个方法进行一个简单的介绍,大家可以了解一下。
open
这个方法里面对属性mysqlCN和mysqlCS进行了初始化,主要就是要建立MySQL数据库的连接和选择tfse数据库。
一般情况下,需要初始化的操作都会单独放到一个对象的方法里面进行处理。
getPendingDomains
这个方法里面通过查询tfse库的websites数据表得到了最前面的若干条网站域名信息。这里面有个小问题,就是如果我们后面不去更新nextFetchDT字段和lastFetchDT字段的值,则这个方法会始终返回相同的若干条网站域名信息了。所以,在后面我们一定要合理的设计如何去更新nextFetchDT和lastFetchDT字段的值来保证爬取的过程是雨露均沾的。
fetchDomainURL
这个方法是蜘蛛程序的关键了,在这个方法里面我们会尝试去访问一个网址(URL),然后分析这个网址的网页信息,并且会去提取更多的子级网址以备今后进行采集分析处理。
这个方法目前只是实现了采集网页的链接这个基础功能,后面我们会逐步对它进行完善。
isWebPage
这个方法福哥没有实现它,它的作用是判断采集到的链接是内部链接还是外部链接,如果是外部链接就意味着这会是另外的一个网站的网页了,我们就需要区别处理了。
saveWebPage
这个方法福哥也没有实现它,它的作用很容易理解,就是要把网页网址保存到webpages数据表里面。
saveDomainPage
这个方法福哥也没有实现它,它的作用也很容易理解,就是要把网址域名保存到websites数据表里面。
close
这个方法需要在全部逻辑执行完毕之后运行,它的作用就是关闭MySQL数据连接,释放资源。
输出
执行主程序会打印爬取网站后得到的域名信息
总结
大家可以看出来福哥给出的这个Spider对象还很不完善,很多方法根本没有去实现它的逻辑。在这里福哥想告诉大家,编写代码就是这样一步一步的推进的,不会有那个程序员可以在一开始就设计好全部需要的对象和函数,进而一一实现它们,最后运行时候还没有任何问题一次通过的,都是需要在逐步推进的过程中一步一步的磨合才能完成的。
另外,福哥会保留一部分关键函数的实现的代码,这些就留给童鞋们自己动脑筋去实现了。还是那句话,完全的代码贴出来,会造成有些童鞋的惰性,直接复制粘贴过来,没有任何营养,这样是无法学好编程的。
P.S.
微信公众号的文章发出去之后是不能编辑的,但是福哥偶尔会修复一些描述不到位、示例不正确、结构不清晰等等的文章错误,这些只能在网站上才能看到最新版本内容,望大家知晓~~