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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,简单介绍下网络爬虫   网络爬虫是通过网页的链接地址来寻找网页,从网站某一个页面(设置为主页)开始,读取网页的内容,找到网页中的其它链接地址,然后通过这些链接地址寻找下一个网页,这样一直循环下去,直到这个网站所有的网页都抓取完为止。实际上,由于抓取技术的限制以及存储技术、处理技术的限制,要完全抓取网站的所有网页是不可能的,也是不实际的!本着从用户需要为出发点,实际需要抓取的网页往往是有限的,只需抓取符合用户要求的网页即可! 抓取网页的策略 在抓取网页的时候,网络爬虫一般有两种策略(即两种搜索方法),广度优先和深度优先。 广度优先:是指网络爬虫会先抓取起始网页中链接的所有网页,然后再选择其中的一个链接网页,继续抓取在此页面中链接的所有页面。这是最常用的方式,广度优先的搜索策略可以并行处理,提高抓取速度。 深度优先:是指网络爬虫会从起始页开始,一个链接一个链接跟踪下去,处理完这条线路之后再转入下一个起始页,继续跟踪链接。这种策略较易实现,但是抓取速度慢。 由于一般不可能抓取网站的所有链接,一般会设置访问层数,即搜索深度。起始页的深度为0,起始页中的链接url深度为1,依此类推。 构造C#语言的爬虫程序 C#已经封装了HTTP访问和多线程,这对编写网络爬虫提供了方便,而要C#网络爬虫程序需要解决以下问题: HTML分析:需要某种HTML解析器来分析爬虫程序遇到的每一个页面。 页面处理:需要处理每一个下载得到的页面。下载得到的内容需要保存起来,以便进一步分析处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值