python分布式爬虫:爬虫基础知识

技术选型

scrapy vs requests + beautifulsoup

1,requests和beautifulsoup都是库,scrapy是框架
2,scrapy框架中可以加入requests和beautifulsoup
3,scrapy基于twisted(异步I/O),性能是最大的优势
4,scrapy方便扩展,提供了很多内置的功能
5,scrapy内置的css和xpath selector非常方便,beautifulsoup最大的缺点就是慢(对HTML进行分析)

网页分类

常见类型的服务
1,静态网页(静态博客)
2,动态网页
3,webservice(restapi)

爬虫能做什么

爬虫作用
1,搜索引擎–百度,google,垂直领域搜索引擎
2,推荐引擎–今日头条
3,机器学习的数据样本
4,数据分析(如金融数据分析),舆情分析等。

正则表达式

目录:
1,特殊字符

  1. ^ $ * ? + {2} {2,} {2,5} |
  2. [] [^] [a-z] .
  3. \s \S \w \W
  4. [\u4E00-\u9FA5] () \d

2,正则表达式的简单应用及python示例
栗子1:

import  re

line = "bobby123"
regex_str = "^b.*"
if re.match(regex_str,line):
    print("yes")

栗子二:

import  re

line = "boooooooobby123"
regex_str = ".*?(b.*?b).*"
mathch_obj = re.match(regex_str,line)
if mathch_obj:
    print(mathch_obj.group(1))

当没有加 ? 的时候是贪婪匹配(从最后开始匹配),加了之后是非贪婪模式(从前面开始匹配)。

注意: [ ] 里面的特殊字符不再有特殊含义,[ * ]就是匹配 *

栗子三:

import  re

line = "你 好"
regex_str = "(你\s好)"
mathch_obj = re.match(regex_str,line)
if mathch_obj:
    print(mathch_obj.group(1))

栗子四:

import  re

line = "你好s"
regex_str = "([\u4E00-\u9FA5]+)"
mathch_obj = re.match(regex_str,line)
if mathch_obj:
    print(mathch_obj.group(1))

使用[\u4E00-\u9FA5]可以匹配连续的中文
我们看下一个字符串中除了中文还有其它字符的时候,我们想提取大学前面和大学

import  re

line = "study in 南京大学"
regex_str = ".*?([\u4E00-\u9FA5]+大学)"
mathch_obj = re.match(regex_str,line)
if mathch_obj:
    print(mathch_obj.group(1))

深度优先和广度优先

目录:
1,网站的树结构
2,深度优先算法和实现
3,广度优先算法和实现

网站url的结构图:伯乐在线

《python分布式爬虫:爬虫基础知识》 Paste_Image.png

网站设计是分层的,多级域名的。

网站url链接的结构图

《python分布式爬虫:爬虫基础知识》 Paste_Image.png

为了防止循环爬取,对已经爬取过的链接新建一个list存放。在爬取之前,我们进行一次判断,如果没有爬取过,才爬取。

深度优先图:

《python分布式爬虫:爬虫基础知识》 Paste_Image.png

深度优先:每次爬取到无链接可爬取为止,然后向上层返回查找。
广度优先:每次爬取当前页面可访问的所有兄弟节点。(分层)
1,深度优先输出A,B,D,E,I,C,F,G,H(递归实现)
2,广度优先输出A,B,C,D,E,F,G,H,I(队列实现)

深度优先过程:

In [1]: def depth_tree(tree_node):
   ...:     if tree_node is not None:
   ...:         print(tree_node._data)
   ...:         if tree_node._left is not None:
   ...:             return depth_tree(tree_node._left)
   ...:         if tree.node._right is not None:
   ...:             return depth_tree(tree_node._right)
   ...:

注意:递归太深会导致栈溢出

广度优先过程:

In [4]: def level_queue(root):
   ...:     """利用队列实现树的广度优先遍历"""
   ...:     if root is None:
   ...:         return
   ...:     my_queue = []
   ...:     node = root
   ...:     my_queue.append(node)
   ...:     while my_queue:
   ...:         node = my_queue.pop(0)
   ...:         print (node.elem)
   ...:         if node.lchild is not None:
   ...:             my_queue.append(node.lchild)
   ...:         if node.rchild is not None:
   ...:             my_queue.append(node.rchild)
   ...:

爬虫去重策略

1,将访问过的url保存到数据库中
(每次拿到一个新的url都会去数据库查询是否被爬取过,效率低)
2,将访问过的url保存到内存set中,只需要O(1)的代价就可以查询url
假设有一亿个url,占用内存:
1000000002byte50个字符/1024/1024/1024 = 9G
3,url经过md5等方法哈希后保存到set
经过编码之后,可以对数据压缩
4,用bitmap方法,将访问过的url通过hash函数映射到某一位
将url映射到byte的位上,但是具有高冲突
5,bloomfilter方法对bitmap进行改进,多重hash函数降低冲突

字符串编码

《python分布式爬虫:爬虫基础知识》 image.png
《python分布式爬虫:爬虫基础知识》 image.png

utf8编码在保存和网络传输的时候,使用的空间较小。
而unicode编码在编程的时候,因为字节统一,便于编程。

因此文件文件保存的时候,我们保存为utf-8的格式,读取到内存的时候,我们转化为Unicode编码。当由内存保存至文件的时候,我们再将编码改为utf-8的编码格式。

《python分布式爬虫:爬虫基础知识》 Paste_Image.png

获取系统默认编码

In [1]: import sys

In [2]: sys.getdefaultencoding
Out[2]: <function sys.getdefaultencoding>

In [3]: sys.getdefaultencoding()
Out[3]: 'utf-8'

想要encode之前要保证字符串是Unicode格式。

    原文作者:海贼之路飞
    原文地址: https://www.jianshu.com/p/350d335a138a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞