编辑推荐:

本文主要介绍了Python实现简易Web爬虫详解,希望对大家有帮助。

本文来自于脚本之家 ,由火龙果软件Alice编辑,推荐。

简介:

网络爬虫(又被称为网页蜘蛛),网络机器人,是一种按照一定的规则,自动地抓信息的程序或者脚本。假设互联网是一张很大的蜘蛛网,每个页面之间都通过超链接这根线相互连接,那么我们的爬虫小程序就能够通过这些线不断的搜寻到新的网页。

Python作为一种代表简单主义思想的解释型、面向对象、功能强大的高级编程语言。它语法简洁并且具有动态数据类型和高层次的抽象数据结构,这使得它具有良好的跨平台特性,特别适用于爬虫等程序的实现,此外Python还提供了例如Spyder这样的爬虫框架,BeautifulSoup这样的解析框架,能够轻松的开发出各种复杂的爬虫程序。

在这篇文章中,使用Python自带的urllib和BeautifulSoup库实现了一个简单的web爬虫,用来爬取每个URL地址及其对应的标题内容。

流程:

爬虫算法从输入中读取的一个URL作为初始地址,向该地址发出一个Request请求。

请求的地址返回一个包含所有内容的,将其存入一个String变量,使用该变量实例化一个BeautifulSoup对象,该对象能够将内容并且将其解析为一个DOM树。

根据自己的需要建立正则表达式,最后借助HTML标签从中解析出需要的内容和新的URL,将新的放入队列中。

对于目前所处的URL地址与爬去的内容,在进行一定的过滤、整理后会建立索引,这是一个单词-页面的存储结构。当用户输入搜索语句后,相应的分词函数会对语句进行分解获得关键词,然后再根据每个关键词查找到相应的URL。通过这种结构,可以快速的获取这个单词所对应的地址列表。在这里使用树形结构的存储方式,Python的字典和列表类型能够较好的构建出单词词典树。

从队列中弹出目前的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 re

import urllib.request

import urllib.parse

from bs4 import BeautifulSoup

class 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, page_url, 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, page_url, html_cont):

if page_url is None or html_cont is None:

return None

soup = BeautifulSoup(html_cont, 'html.parser',

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, url, word)

return index

def add_key_index(self, index, url, 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,url2,...,urln],...}

每个url及其页面中包含的urls,url-suburls索引,如下

graph={'url':[url1,url2,...,urln],...}

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写一个简单的爬虫_Python实现简易Web爬虫详解相关推荐

  1. python爬虫抢火车票_如何用python写一个简单的12306抢票软件|python 爬火车票 教程...

    python 如果抓取验证码图片 类似12306的登录验证码图片 这个以前做次.最大的麻烦是码的识别算法的识别率太低.12306那种网站登陆错3次就限制你20分钟.所以除非你有33%以上的识别率否则不 ...

  2. 用python写一个简单的web服务器

    人生苦短,我用python 简洁高效,这才是理想的语言啊 分享一点python的学习经验-----如何用python写一个简单的web服务器 首先,我们需要简单地了解一下网络通信协议,这里用白话介绍一 ...

  3. 利用python写一个简单的双色球彩票系统

    利用python写一个简单的双色球彩票系统 1.设置每次买的号码一样 写一个双色球彩票系统,系统可以随机产生一组数据,一组彩票数据有六位数,这六位数的的取值范围是0和1. 一张彩票是两块钱,用户可以选 ...

  4. 用Python写一个简单的双均线策略分析

    用Python写一个简单的双均线策略 双均线策略 先罗列一下我知道的量化策略: 双均线:一句话来讲就是金叉买死叉卖. 布林带:突破压力线(上轨)清仓,跌破支撑线(下轨)持仓. PEG:根据PE/G调整 ...

  5. 用python写一个文件管理程序下载_Python管理文件神器 os.walk

    原标题:Python管理文件神器 os.walk 来自:CSDN,作者:诡途 [导语]:有没有想过用python写一个文件管理程序?听起来似乎没思路?其实是可以的,因为Python已经为你准备好了神器 ...

  6. python解析器是什么_如何用python写一个简单的词法分析器

    编译原理老师要求写一个java的词法分析器,想了想决定用python写一个. 目标 能识别出变量,数字,运算符,界符和关键字,用excel表打印出来. 有了目标,想想要怎么实现词法分析器. 1.先进行 ...

  7. python可以做机器人吗_零基础如何用Python写一个简单的WeChat机器人?(内附代码)...

    (bing图片) python这两年热火朝天,依托其众多类库,基于python的应用层出不穷,也大大降低了非计算机专业人员的入门门槛,WeChat机器人自然不在话下!-- 聪明的瓦肯人 苦于有时候总是 ...

  8. python写词法分析器_如何用python写一个简单的词法分析器

    编译原理老师要求写一个java的词法分析器,想了想决定用python写一个. 目标 能识别出变量,数字,运算符,界符和关键字,用excel表打印出来. 有了目标,想想要怎么实现词法分析器. 1.先进行 ...

  9. python写词法分析器_用python写一个简单的词法分析器

    编译原理老师要求写一个java的词法分析器,想了想决定用python写一个. 目标 能识别出变量,数字,运算符,界符和关键字,用excel表打印出来. 有了目标,想想要怎么实现词法分析器. 1.先进行 ...

最新文章

  1. JPA 2.2改进了易用性
  2. 【集合论】关系性质 ( 常见的关系的性质 | 关系性质示例 | 关系运算性质 )
  3. 使用 Intel HAXM 为 Android 模拟器加速,媲美真机(转)
  4. Android基于监听的事件处理机制
  5. VTK修炼之道38:图像平滑_中值滤波器
  6. isinstance函数
  7. 只因写了一段爬虫,公司200多人被抓 ?
  8. 台式电脑键盘按键错乱_电脑键盘各个按键有哪些作用 电脑键盘各个按键作用介绍...
  9. GridView导出为Excel
  10. 魔方阵(奇数,单偶,双偶)
  11. php计算字符串散列,php计算字符串的SHA-1散列函数sha1()
  12. 15-07-06 定闹钟
  13. Swift面向对象基础(上)——Swift中的枚举
  14. GitHub上README写法暨markdown语法解读
  15. org.mybatis.caches.ehcache.LoggingEhcache
  16. 减法公式运算法则_加减法运算法则
  17. 北方工业大学计算机复试分数线,北方工业大学2017年复试分数线
  18. python 函数进阶_python之函数进阶
  19. 比入赘还简单的——Python Flask Web 框架入门
  20. 邵阳学院计算机系主任,湖南教育大平台-湖南省计算机教育年会在邵阳学院召开...

热门文章

  1. Hibernate中两种获取Session的方式
  2. 自己动手制作的一个JDBC的套件封装,求指导
  3. 参加51CTO学院软考培训,我通过啦!
  4. [Javascipt] Immediately-Invoker 2
  5. linux cpu占用率 监控工具 简介
  6. docker 安装iproute包 包含 ss ip 命令
  7. cmake 编译选项 add_compile_options CMAKE_CXX_FLAGS 区别
  8. mysql 加密方式 caching_sha2_password 和 mysql_native_password 说明
  9. linux c 字符串函数 replace indexOf substring 实现
  10. debian apt-get 更新源文件格式说明