介绍
在不借助爬虫框架的情况下,自定义爬虫程序的代码结构,整体可以分为请求发送器、数据解析器、数据保存器、URL管理器、任务调度器和执行入口几部分。
我们这里以爬取小说网站的书名和分页列表为例
1、请求发送器
模拟请求头,发送请求并获取返回信息
import requests
from fake_useragent import UserAgent
from lxml import etree
# 请求发送器
class Downloader():
def do_downloader(self, url):
print(url)
headers = {'User-Agent': UserAgent().random}
resp = requests.get(url, headers=headers)
if resp.status_code == 200:
# resp.encoding = 'utf-8'
print(resp.text)
return resp.text
2、数据解析器
使用xpath
解析获取的数据,提取小说名称和分页url地址
# 数据解析器
class Parser():
def do_parse(self, html):
e = etree.HTML(html)
contents = [div.xpath('string(.)').strip() for div in e.xpath('//div[@class="book-name"]')]
urls = ['http://www.shuhai.com{}'.format(url) for url in e.xpath('//div[@class="page3"]/a/@href')]
return contents, urls
3、数据保存器
将数据持久化到mydata.txt
文件中
# 数据保存器
class DataSave():
def do_save(self, datas):
with open('mydata.txt', 'a', encoding='utf-8') as file:
for data in datas:
file.write(data + '\n')
4、URL管理器
创建两个url容器,new_url
存入新获取的url地址,old_url
存入已经使用完的url地址,这样方便进行进行去重、判空等操作
# URL管理器
class UrlManager():
def __init__(self):
self.new_url = set()
self.old_url = set()
# 加入一个url
def add_new_url(self, url):
if url is not None and url != '' and url not in self.old_url:
self.new_url.add(url)
# 加入多个url
def add_new_urls(self, urls):
for url in urls:
self.add_new_url(url)
# 获取一个url
def get_new_url(self):
url = self.new_url.pop()
self.old_url.add(url)
return url
# 获取剩下的url个数
def get_new_url_size(self):
return len(self.new_url)
# 判断是否还剩url未爬取
def is_have_new_url(self):
return self.get_new_url_size() > 0
5、任务调度器
初始化其它类,并循环访问容器中的url地址,直到消费完最后一个
# 任务调度器
class Scheduler:
def __init__(self):
self.downloader = Downloader()
self.parser = Parser()
self.save = DataSave()
self.url_manager = UrlManager()
def start(self, url):
self.url_manager.add_new_url(url)
while self.url_manager.is_have_new_url():
url = self.url_manager.get_new_url()
html = self.downloader.do_downloader(url)
datas, urls = self.parser.do_parse(html)
self.save.do_save(datas)
self.url_manager.add_new_urls(urls)
6、执行入口
输入开始地址,调用任务调度器
# 执行入口
if __name__ == '__main__':
scheduler = Scheduler()
# 开启地址
url = 'http://www.shuhai.com/shuku/1_0_0_0_0_0_0_1.html'
scheduler.start(url)