python爬虫设计思路_python网络爬虫(9)构建基础爬虫思路
目的意义
基础爬虫分5个模块,使用多个文件相互配合,实现一个相对完善的数据爬取方案,便于以后更完善的爬虫做准备。
这里目的是爬取200条百度百科信息,并生成一个html文件,存储爬取的站点,词条,解释。
功能模块
主文件:爬虫调度器,通过调用其他文件中的方法,完成最终功能实现。
其他文件:URL管理器,HTML下载器,HTML解析器,数据存储器。
设计思路
定义SpiderMan类作为爬虫调度器。输入根URL开始爬取数据然后爬取结束。
在爬取过程中,需要获取网页,和解析网页。
解析网页需要HTML解析器,获取网页需要HTML下载器。
解析网页需要解析的数据有:URL,TITLE,CONTEXT等。则需要URL管理器和数据存储器。
主文件设计
主文件添加根URL,然后提取该URL,下载该URL内容。
根据内容,调用解析器:
解析出该URL中的新URL,存入URL管理器;
解析出该URL中的标题,文本等信息,存入数据存储器。
完成后开始下一次。这时URL管理器多出了新的URL,提取出新的URL,下载,解析,不断重复即可。
重复结束以提取出的URL数量超过200则结束。
代码如下:
from BaseSpider.DataOutput import DataOutput
from BaseSpider.HtmlDownloader import HtmlDownloader
from BaseSpider.HtmlParser import HtmlParser
from BaseSpider.UrlManager import UrlManager
class SpiderMan():
def __init__(self):
self.manager=UrlManager()
self.downloader=HtmlDownloader()
self.parser=HtmlParser()
self.output=DataOutput()
def crawl(self,root_url):
self.manager.add_new_url(root_url)
while(self.manager.has_new_url() and self.manager.old_url_size()<200):
new_url=self.manager.get_new_url()
text=self.downloader.download(new_url)
if text is None:
print('None text')
break
new_urls,data=self.parser.parser(new_url,text)
self.manager.add_new_urls(new_urls)
self.output.store_data(data)
print(self.manager.old_url_size())
self.output.output_html()
if __name__ == "__main__":
spider_man=SpiderMan()
spider_man.crawl("https://baike.baidu.com/item/%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB/5162711?fr=aladdin")
print('finish')
作为最初的设计,应该允许异常抛出,便于查看程序终止的原因,然后排查错误。
HTML下载器设计
下载网页,返回文本。即可。
import requests
import chardet
class HtmlDownloader(object):
def download(self,url):
if url is None:
return None
user_agent='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0'
headers={'User-Agent':user_agent}
r=requests.get(url,headers=headers)
if r.status_code is 200:
r.encoding=chardet.detect(r.content)['encoding']
return r.text
return None
HTML解析器设计
HTML解析器将下载的文本进行解析,需要解析出的数据有:页面的新URL,页面的新数据文本。
建立相应的解析器,需要打开源码对比,然后进行使用源码分析,使用BeautifulSoup获取所需信息。
为了便于主函数调用或者其他原因,将所有数据通过parser实现返回,其parser分别调用获取URL和获取数据文本的信息。
为了处理一些不同网页可能抓取的意外情况导致程序终止,添加了一些判断。
import re
from urllib import parse
from bs4 import BeautifulSoup
class HtmlParser(object):
def parser(self,page_url,html_cont):
if page_url is None or html_cont is None:
return
soup=BeautifulSoup(html_cont,'lxml')
new_urls=self.getNewUrls(page_url,soup)
new_data=self.getNewData(page_url,soup)
return new_urls,new_data
def getNewUrls(self,page_url,soup):
new_urls=set()
links=soup.find_all('a',href=re.compile(r'/item/.*'))
for link in links:
new_url=link['href']
new_full_url=parse.urljoin(page_url,new_url)
new_urls.add(new_full_url)
return new_urls
def getNewData(self,page_url,soup):
data={}
data['url']=page_url
title=soup.find('dd',class_="basicInfo-item value")
if title is not None:
data['title']=title.string
summary=soup.find('meta',attrs={"name":"description"})
data['summary']=summary['content']
return data
else:
title=soup.find('meta',attrs={"name":"keywords"})
if title is not None:
data['title']=title['content']
summary=soup.find('meta',attrs={"name":"description"})
data['summary']=summary['content']
return data
else:
data['title']="ERROR!"
data['summary']="Please check the url for more information"
data['url']=page_url
return data
URL管理器设计
使用old_urls存储已经访问过的网址,使用new_urls存入将要提取的网址。
然后写好has_new_url等方法,辅助主程序调用。当得到新的URL们时,主程序调用函数将他们存入。
而主程序需要的其他URL管理方案,如提取,数量判定等,也在这里实现。
class UrlManager():
def __init__(self):
self.old_urls=set()
self.new_urls=set()
pass
def has_new_url(self):
return self.new_url_size()!=0
def new_url_size(self):
return len(self.new_urls)
def old_url_size(self):
return len(self.old_urls)
def get_new_url(self):
new_url=self.new_urls.pop()
self.old_urls.add(new_url)
return new_url
def add_new_url(self,url):
if url is None:
return
if url not in self.new_urls and url not in self.old_urls:
self.new_urls.add(url)
pass
def add_new_urls(self,urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
pass
数据存储器设计
通过HTML解析器获取的数据,通过数据存储器进行存储。
而最终将数据从内存写入到本地磁盘,也在该文件实现。
为了调试美观,建议是先爬取一两个数据做好测试,写好table的宽度设定,加入style='word-break:break-all;word-wrap:break-word;'参数。参阅:https://zhidao.baidu.com/question/1385859725784504260.html
import codecs
class DataOutput(object):
def __init__(self):
self.datas=[]
def store_data(self,data):
if data is None:
return
self.datas.append(data)
def output_html(self):
fout=codecs.open('baike.html', 'w', encoding='utf-8')
fout.write("")
fout.write("
")
fout.write("
")
fout.write("
fout.write("
")
fout.write("
URL")
fout.write("
标题")
fout.write("
释义")
fout.write("
")
for data in self.datas:
fout.write("
")
fout.write("
%s"%(data['url'],data['url']))
fout.write("
%s"%data['title'])
fout.write("
%s"%data['summary'])
fout.write("
")
fout.write("
")
fout.write("")
fout.write("")
fout.close()
最终效果:
当然还有一些数据没有处理好。
完
原文出处:https://www.cnblogs.com/bai2018/p/10994735.html
python爬虫设计思路_python网络爬虫(9)构建基础爬虫思路相关推荐
- python sub 不区分大小写_Python网络爬虫入门篇
1. 预备知识 学习者需要预先掌握Python的数字类型.字符串类型.分支.循环.函数.列表类型.字典类型.文件和第三方库使用等概念和编程方法. Python入门篇:https://www.cnblo ...
- python爬虫实践报告_Python网络爬虫从入门到实践
本书讲解了如何使用Python编写网络爬虫,涵盖爬虫的概念.Web基础.Chrome.Charles和Packet Capture抓包.urllib.Requests请求库.lxml.Beautifu ...
- python爬虫和定位_Python网络爬虫实战,照片定位与B站弹幕!
之前两篇已经说完了如何爬取网页以及如何解析其中的数据,那么今天我们就可以开始第一次实战了. Python资源共享群:626017123 这篇实战包含两个内容. * 利用爬虫调用Api来解析照片的拍摄位 ...
- python爬虫和定位_Python网络爬虫实战(三)照片定位与B站弹幕
之前两篇已经说完了如何爬取网页以及如何解析其中的数据,那么今天我们就可以开始第一次实战了. 这篇实战包含两个内容. * 利用爬虫调用Api来解析照片的拍摄位置 * 利用爬虫爬取Bilibili视频中的 ...
- unet网络python代码详解_python网络编程详解
最近在看<UNIX网络编程 卷1>和<FREEBSD操作系统设计与实现>这两本书,我重点关注了TCP协议相关的内容,结合自己后台开发的经验,写下这篇文章,一方面是为了帮助有需要 ...
- python编程设计高级_Python高级应用程序设计
一.主题式网络爬虫设计方案(15分) 1.主题式网络爬虫名称 链家二手房成交信息(福州地区) 2.主题式网络爬虫爬取的内容与数据特征分析 本爬虫程序爬取链家网福州二手房的成交信息,分别从户型.面积.成 ...
- python的设计哲学_Python 的设计哲学
The Zen of Python, by Tim Peters Python 的设计哲学,作者:Tim Peters Beautiful is better than ugly. 优雅胜于丑陋. E ...
- python网络爬虫文献综述_python网络爬虫综述
本文主要是个人python学习过程中的碎碎念想,希望对感兴趣的童鞋有所帮助. 百度百科上网络爬虫的定义是:"网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者 ...
- python 爬虫热搜_Python网络爬虫之爬取微博热搜
微博热搜的爬取较为简单,我只是用了lxml和requests两个库 1.分析网页的源代码:右键--查看网页源代码. 从网页代码中可以获取到信息 (1)热搜的名字都在 的子节点里 (2)热搜的排名都在 ...
最新文章
- 【管理心得之一】不要用“可有可无”的事,挑战他人对这件事的原则和底线...
- 基准测试:Apache Ignite仍然领先于Hazelcast
- Linux 启动失败 磁盘阵列,组建RAID5重启系统,出现md127的解决办法
- ril.java_RIL.java里request流程
- JavaScript(八)—— PC 端网页特效
- mysql死锁语句_记一次神奇的Mysql死锁排查
- json 来实现 php 与 javascript,用 Json 来实现 PHP 与 JavaScript 间数据交换
- mysql 集群怎么卸载节点_Redis集群重新分片(新增/移除节点)【理论】
- springboot学习笔记-3 整合redismongodb
- HashMap原理剖析
- 今年Java面试必问的这些技术面,赶快收藏备战金九银十!
- 《电路》邱关源 思维导图 第七章-一阶和二阶电路的时域分析
- 腾讯CJ放出大招!次世代手游大作曝光,画面堪比3A大作
- processing交互应用——双人对战游戏
- JavaScript BOM和DOM部分
- Python小白机器学习教程:Sklearn精讲
- python egg_python egg 简介
- grant change notification to 用户名的探究
- hbase连接数据库
- 大数据之于智能交通意义重大仍面临五大难题
热门文章
- Win11右键菜单切回经典模式
- FFmpeg之获取音视频信息(二十八)
- C++之=deleted
- ubuntu修改启动项等待时间、修改启动项顺序、更改启动内核
- 新手建站虚拟主机与云服务器应该如何选择?
- 每日三道前端面试题--vue 第二弹
- 响应已被截断_技术:RWD响应式网站网页设计基本原则
- 基于信息熵确立权重的topsis法_基于信息熵和TOPSIS法的装备战场抢修排序决策模型...
- django如何连接mysql_Django如何连接mysql
- linux mint 安装内核,使用Ukuu在Ubuntu/Linux Mint上安装Linux Kernel 5.0的方法