start
上一节,我们爬取图片,这一节,我们来改写上一节爬虫,根据【高内聚低耦合】的思想
【高内聚低耦合】是一种面向对象的编程思想,意思是一个程序,把各个功能分成模块来写,一个模块只完成一个功能,而各个模块之间又相互联系在一起,组成完整的程序,每个模块的改动对其他模块的影响小(低耦合),每个模块的功能实现得好(高内聚)
这样写的好处是便于维护,逻辑结构更清晰,在爬虫中也是一样的道理,可能有些童鞋听过了爬虫框架【scrapy】,这个框架的原理就是基于这样来架构的,明白了这个,【scrapy】是怎么运作的就更容易理解一点
在爬虫中,分为 5 个模块:
【spiderMan】:主模块,运行的,【scrapy】中叫调度模块
【urlManager】:url 管理模块,专门管理调用需要的 url,记录爬过的 url,去重等
【htmlDownload】:html 下载请求模块,请求用的
【parseData】:数据解析模块,提取数据用
【dataOupt】:数据输出模块,数据输出时用
由于上节说过了怎么提取下载图片,这里直接给出 5 个模块的代码
创建时,他们放在同一个目录下
spiderMan.py
from urlManager import urlManager
from htmlDownload import htmlDownload
from parseData import parseData
from dataOutput import dataOutput
import time
class spider():
'''
爬虫主逻辑
'''
def __init__(self):
'''
初始化各个模块
'''
self.manager = urlManager()
self.download = htmlDownload()
self.parse = parseData()
self.output = dataOutput()
def start(self):
'''
爬虫开始
:return:
'''
urls = self.manager.get_url()
for url in urls:
html = self.download.get_html(url)
if html == None:
continue
img_urls = self.parse.get_infos(html)
self.output.download_img(img_urls)
time.sleep(1)
if __name__ == '__main__':
'''
主接口
'''
spider = spider()
spider.start()
urlManager.py
class urlManager():
'''
管理 url 模块
'''
def __init__(self):
'''
初始化 url
'''
self.urls = ['https://pixabay.com/zh/images/search/?pagi={}'
.format(str(i)) for i in range(1,10570)]
def get_url(self):
'''
返回页面 url
:return:
'''
return self.urls
htmlDownload.py
import requests
from fake_useragent import UserAgent
class htmlDownload():
'''
下载 html 模块
'''
def get_html(self,url):
"""
请求 url 获得 html
:param url:
:return:
"""
headers = {
'User-agent': UserAgent().random
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
response.encoding = 'utf-8'
return response.text
else:
return None
parsesData.py
import re
class parseData():
'''
解析提取数据模块
'''
def get_infos(self,html):
'''
提取图片 url
:param html:
:return:
'''
urls = re.findall('<img srcset=".*?" src="(.*?)" alt=',
html, re.S)
return urls
dataOutput.py
import os
import requests
from fake_useragent import UserAgent
class dataOutput():
'''
数据输出模块
'''
def download_img(self,img_urls):
'''
下载图片
:param img_urls:
:return:
'''
for url in img_urls:
root = 'image/'
path = root + url[-15:]
if not os.path.exists(root):
os.mkdir(root)
if not os.path.exists(path):
response = requests.get(url, headers={'User-agent': UserAgent().random})
with open(path, 'wb') as f:
f.write(response.content)
print('保存成功')
else:
print('图片存在')
end
运行时时运行 spiderMan.py 模块,虽然代码量比上一节的面向过程多了些,但如果写一些比较复杂的爬虫,使用这种形式,逻辑结构会清晰一些