简介:
网络爬虫(又被称为网页蜘蛛),网络机器人,是一种按照一定的规则,自动地抓信息的程序或者脚本。假设互联网是一张很大的蜘蛛网,每个页面之间都通过超链接这根线相互连接,那么我们的爬虫小程序就能够通过这些线不断的搜寻到新的网页。
Python作为一种代表简单主义思想的解释型、面向对象、功能强大的高级编程语言。它语法简洁并且具有动态数据类型和高层次的抽象数据结构,这使得它具有良好的跨平台特性,特别适用于爬虫等程序的实现,此外Python还提供了例如Spyder这样的爬虫框架,BeautifulSoup这样的解析框架,能够轻松的开发出各种复杂的爬虫程序。
在这篇文章中,使用Python自带的urllib和BeautifulSoup库实现了一个简单的web爬虫,用来爬取每个URL地址及其对应的标题内容。
流程:
爬虫算法从输入中读取的一个URL作为初始地址,向该地址发出一个Request请求。
请求的地址返回一个包含所有内容的,将其存入一个String变量,使用该变量实例化一个BeautifulSoup对象,该对象能够将内容并且将其解析为一个DOM树。
根据自己的需要建立正则表达式,最后借助HTML标签从中解析出需要的内容和新的URL,将新的放入队列中。
对于目前所处的URL地址与爬去的内容,在进行一定的过滤、整理后会建立索引,这是一个单词-页面的存储结构。当用户输入搜索语句后,相应的分词函数会对语句进行分解获得关键词,然后再根据每个关键词查找到相应的URL。通过这种结构,可以快速的获取这个单词所对应的地址列表。在这里使用树形结构的存储方式,Python的字典和列表类型能够较好的构建出单词词典树。
从队列中d出目前的URL地址,在爬取队列不为空的条件下,算法不断从队列中获取到新的网页地址,并重复上述过程。
实现:
环境:
python3.5orAnaconda3
BeautifulSoup4
可以使用下面的指令安装BeautifulSoup4,如果你是Ubuntu用户,记得在命令前面加上sudo:
pip install beautifulsoup4
程序分别实现了几个类,分别用于URL地址管理,HTML内容请求、HTML内容解析、索引建立以及爬虫主进程。我将整个程序按照每个Class分开解释,最后只要将他们放在一起就可以执行代码了。
UrlManager类
这个类用来管理URL地址,new_urls用来保存还未爬取的URL地址,old_urls保存了已经爬取过的地址,两个变量都使用set类型保证其中内容的唯一性。每次循环时,add_new_urls()向外提供了向new_urls变量中添加新urls的方法;add_new_url()方法,对每个URL地址进行重复性检查,符合条件的才进行添加 *** 作;get_urls()向外提供了获取新的URL地址的方法;has_new_url()方法用来检查爬取队列是否为空。
import reimport urllib.requestimport urllib.parsefrom bs4 import BeautifulSoupclass UrlManager(object): def __init__(self): self.new_urls = set() self.old_urls = set() 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) 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 len(self.new_urls) != 0 def get_new_url(self): new_url = self.new_urls.pop() self.old_urls.add(new_url) return new_url
HTMLDownloader类
这个类实现了向URL地址发送Request请求,并获取其回应的方法,调用类内的download()方法就可实现。这里要注意的是页面的编码问题,这里我使用的是UTF-8来进行decode解码,有的网页可能使用的是GBK编码,要根据实际情况进行修改。
class HTMLDownloader(object): def download(self,url): if url is None: return None try: request = urllib.request.Request(url) response = urllib.request.urlopen(request) content = response.read().decode('utf-8').encode('utf-8') if content is None: return None if response.getcode() != 200: return None except urllib.request.URLError as e: print(e) return None return content
HTMLParser类
这个类通过实例化一个BeautifulSoup对象来进行页面的解析。它是一个使用Python编写的HTML/XML文档解析器。它通过将文档解析为DOM树的方式为用户提供需要抓取的数据,并且提供一些简单的函数用来处理导航、搜索、修改分析树等功能。
该类的关键是_get_new_urls()、_get_new_content()、get_url_Title()三个方法。第一个方法用来解析出页面包含的超链接,最为重要的选择要解析的标签并为其构造合适的正则表达式。这里我为a标签定义了一个匹配正则,用来获取所有的站内链接,如下:
links = soup.find_all('a',href=re.compile(r'^(%s).*(/|HTML)$' % self.domain))`
后面的两个类都是通过解析HTML标签来获取Title的方法,最终在parse()中通过调取_get_new_content()来获得Title内容。具体的标签访问方法不细谈了,读者可以自己翻阅BeautifulSoup的官方文档。
class HTMLParser(object): def __init__(self,domain_url): self.domain = domain_url self.res = HTMLDownloader() def _get_new_urls(self,page_url,soup): new_urls = set() links = soup.find_all('a',href=re.compile(r'^(%s).*(/|HTML)$' % self.domain)) try: for link in links: new_url = link['href'] new_full_url = urllib.parse.urljoin(self.domain,new_url) new_urls.add(new_full_url) new_urls = List(new_urls) return new_urls except AttributeError as e: print(e) return None def _get_new_content(self,soup): try: Title_name = soup.Title.string return Title_name except AttributeError as e: print(e) return None def get_url_Title(self): content = self.res.download(self.domain) try: soup = BeautifulSoup(content,'HTML.parser',from_enCoding='utf-8') Title_name = soup.Title.string return Title_name except: Title_name = 'None Title' return Title_name def parse(self,HTML_cont): if page_url is None or HTML_cont is None: return None soup = BeautifulSoup(HTML_cont,from_enCoding='utf-8') new_data = self._get_new_content(page_url,soup) new_urls = self._get_new_urls(page_url,soup) return new_urls,new_data
Buildindex
该类为每个URL地址与他的标题包含的关键词建立了一个索引关系并保存在一个Dict变量中,每个标题对应多个关键词,每个标题也对应多个URL地址,因此每个关键词也对应了多个URL地址,具体的形式如下:
index={'keyword':[url1,url2,...,urln],...}
其中,add_page_index()方法对每个标题进行了分词处理,并且调用了add_key_index()方法将keyword-url的对应关系存到索引中,这其中也进行了重复检查。主意,这个分词方法仅限于英文句子,中文的话需要用到特定的分词工具。
class Buildindex(object): def add_page_index(self,index,url,content): words = content.split() for word in words: index = self.add_key_index(index,word) return index def add_key_index(self,keyword): if keyword in index: if url not in index[keyword]: index[keyword].append(url) else: temp = [] index[keyword] = temp index[keyword].append(url) return index
SpIDerMain
这是爬虫的主题类,它通过调用其他几个类生成的对象来实现爬虫的运行。该类实例化的时候会永久生成上面几个类的对象,当通过craw()方法获取到用户提供的URL地址时,就会依次进行请求、下载、解析、建立索引的工作。最后该方法会返回index,graph两个变量,他们分别是:
每个关键词集齐对应的地址,keyword-urls索引,如下
index={'keyword':[url1,...}
每个url及其页面中包含的urls,url-suburls索引,如下
graph={'url':[url1,...}
class SpIDerMain(object): def __init__(self,root_url): self.root_url = root_url self.urls = UrlManager() self.downloader = HTMLDownloader() self.parser = HTMLParser(self.root_url) self.build = Buildindex() def craw(self): index = graph = {} self.urls.add_new_url(self.root_url) while self.urls.has_new_url(): try: new_url = self.urls.get_new_url() HTML_cont = self.downloader.download(new_url) new_urls,new_Title = self.parser.parse(new_url,HTML_cont) index = self.build.add_page_index(index,new_url,new_Title) graph[new_url] = List(new_urls) self.urls.add_new_urls(new_urls) except Exception as e: print(e) return None return index,graph
最后,我们在程序中添加下面的代码,就可以成功的执行我们的爬虫了
if __name__ == '__main__': spIDer = SpIDerMain('http://www.xael.org/') index,graph = spIDer.craw() print(index) print(graph)
总结
以上就是本文关于Python实现简易Web爬虫详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
总结以上是内存溢出为你收集整理的Python实现简易Web爬虫详解全部内容,希望文章能够帮你解决Python实现简易Web爬虫详解所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)