基础爬虫的五个模块
对书籍《Python爬虫开发与项目实战》147页的理解
部分修改后的原始代码在末尾
五个模块分别是 调度器,url管理器,下载器,解析器,数据导出器
一个感性的认识!![image]()
分为三个相对独立的部分
数据导出的部分是A
是我们的写爬虫的目的,但其本身不影响爬虫运行,你可以用桶接水车运送的水,也可以任由它自由流动
核心部分是B
不停旋转把需要的资源抽出来送到指定地方,关键数据是url 由url管理器,下载器,解析器组成
调度器是C
可以想象是一个人把水车架设好,加初始水让核心部分转起来,之后判断选旋转次数是否达标,及时停止核心部分运行
各模块
下载器:
接受一个url :返回网页内容
简单情况下就是一行代码
return requests.get(url,headers=user_agent).text
但这里是用一个类实现的,这里五个模块都是以类的形式实现 看起来好像是多此一举,这里是为了通用性,一些post方式请求,需要提供的参数要额外生成可能会变得很复杂,但在这个框架下,代码还是很清晰
url管理器:
接受多个url:每次调用返回一个url
爬取到最后新获取到的url会是已爬取url实际不会添加,所以不会出现爬不完的现象
两个集合分别存放添加后还没爬取的链接,爬取后的链接
网页解析后通常会获取多个链接
基本方法有 添加多个url 获取一个url
最初需要添加一个url启动循环,可以以列表形式 添加,但形式上看着还是不舒服,这里又添加了一个方法 添加一个url 基本方法里的添加多个url实现变成了循环调用添加单个url的方
为了方便添加了判断待爬集合是否为空,分别获取两个集合的大小的函数
解析器:
接受网页内容:新爬取url,需要的数据
新url是给循环部分使用的,数据部分给数据存储使用,流到A部分,推荐以字典形式返回
基本犯法 url解析,数据解析
数据导出器:
接受数据:保存数据
基本方法 临时存储变量,数据写入到磁盘
几十条数据可以在爬取结束后调用 写入磁盘函数,数据大可按记录添加次数,每添加10次自动写入磁盘一次,注意写入磁盘后清空原数据变量
调度器:
初始化其他模块,给url添加第一个url
循环中调用各模块中的方法 判断url管理器中已爬取url是否满足要求,及时停止运行
测试运行提示,添加第一个url 设置主站url
形式如下:
https://www.bilibili.com/video/dsadsa
改变解析器中url解析规则,可这直接获取所有链接再判断链接的形式是否和video/xxx一样
数据解析部分,可直接返回解释url的结果
数据导出部分可直接输出查查看效果
点击查看代码
import requests
from lxml import etree
class Url_Manager():
def __init__(self):
self.new_url = set()
self.old_url = set()
def get_new_url(self):
url = self.new_url.pop()
self.old_url.add(url)
return url
def add_new_url(self, url):
if url is None:
return
if not url in self.new_url and not url in self.old_url:
self.new_url.add(url)
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
def has_new_url(self):
return self.new_url != 0
def new_urls_size(self):
return len(self.new_url)
def old_urls_size(self):
return len(self.old_url)
class Html_Downloader():
def download(self,url):
if url is None:
return
user_agent={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.55' }
response=requests.get(url,headers=user_agent)
if response.status_code==200:
return response.text
class Data_output():
def __init__(self):
self.data=[]
self.conn,self.cur=self.con_db()
self.cnt=0
def store_data(self,data):
if data is None:
return
self.data.append(data)
self.cnt+=1
if self.cnt%10==0:
self.out_put_any()
def out_put_any(self):
for item in self.data:
for i in item:
url,cla,title=i
sql=f'insert into a values("{title}","{cla}","{url}")'
try:
self.cur.execute(sql)
except:
pass
self.conn.commit()
self.data = []
print(f'out {self.cnt}')
def con_db(self):
import sqlite3
conn=sqlite3.connect(r'data.db')
cur=conn.cursor()
try :
cur.execute('create table a ("title" text,"cla" text,"url" text primary key)')
conn.execute()
except:
print('table exist ')
return conn,cur
class Html_Parser():
def parser(self,page_url,content):
if page_url is None or content is None:
return
soup=etree.HTML(content)
new_urls=self.get_newurls(page_url,soup)
new_data = self.get_newdata(page_url,soup)
return new_urls ,new_data
def get_newurls(self,page_url,html):
urls=[]
all_item=html.xpath('//a')
for item in all_item:
# title=item.xpath('./a/@title')[0]
href=item.xpath('./@href')
if href and'index.php/art/type/id' in href[0]:
url=page_url+href[0]
urls.append(url)
return urls
def get_newdata(self,page_url,html):
cla=html.xpath('//div[@class="panel-heading"]/text()')
if cla:
cla=cla[0].strip()
urls=[]
paras=html.xpath('//tr')
for item in paras:
title=item.xpath('./td/a/@title')
href=item.xpath('./td/a/@href')
if title and href:
url=page_url+href[0]
title=title[0]
urls.append([url,cla,title])
data= urls
return data
class Spider_Man():
def __init__(self):
self.manager=Url_Manager()
self.downloader=Html_Downloader()
self.parser=Html_Parser()
self.output=Data_output()
def crawler(self,root_url):
page_url='page_url'
if root_url is None:
return
self.manager.add_new_url(root_url)
while self.manager.has_new_url() and self.manager.old_urls_size() <10:
try:
url=self.manager.get_new_url()
html=self.downloader.download(url)
urls,data=self.parser.parser(page_url,html)
self.manager.add_new_urls(urls)
self.output.store_data(data)
# {self.manager.old_urls_size()}
print(f'.',end=' ')
except:
print('anything is wrong')
self.output.out_put_any()
if __name__=='__main__':
url='url'
spi=Spider_Man()
spi.crawler(url)


浙公网安备 33010602011771号