python 爬虫基本组成

本文参考自python 爬虫基本组成

查看原文: 原文地址

基本组成

爬虫通常分为数据采集(网页下载)、数据处理(网页解析)和数据存储(有用的信息持久化)三个部分。

工作流程:

  1. 设定抓取目标(种子页面/起始页面)并获取网页。

  2. 当服务器无法访问时,按照指定的重试次数尝试重新下载页面。

  3. 在需要的时候设置用户代理或隐藏真实IP,否则可能无法访问页面。

  4. 对获取的页面进行必要的解码操作然后抓取出需要的信息。

  5. 在获取的页面中通过某种方式(如正则表达式)抽取出页面中的链接信息。

  6. 对链接进行进一步的处理(获取页面并重复上面的动作)。

  7. 将有用的信息进行持久化以备后续的处理。

解析工具

urllib

urllib.request 中的 Request urlopen

页面内容抓取工具

正则、lxml、bs4(BeautifulSoup)

lxml

etree.HTML(): 解析HTML对象

  
  
  etree = etree.HTML(html)
  etree.xpath()

xpath 语法

表达式 作用
/ 根节点选取
// 在当前选择的文档中选取
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性

beautifulSoup

安装包

  • pip install beautifulsoup4

导入包

  • form bs4 import BeautifulSoup

1. 简单使用

beautifulSoup得到的是一个 bsObj 我们可以在它的基础上进行获取我们需要的信息

  
  
  from urllib.request import urlopen
  from bs4 import BeautifulSoup
  
  html = urlopen('')
  bsObj = BeautifulSoup(html.read())
  print(bsObj.h1)  # 获取 h1 标签
  
  # 获取 标签中的 class='green'的 span
  span = bsObj.findAll('span', {'class': 'green'})
  
  # 获取文本信息
  span.get_text()
  
  # 获取属性值
  span.attrs.get('attr')
  span.get('attr')
  
  

在获取文本信息时, 会将所有的标签信息都清除, 应该尽量避免这样, 尽量保存 HTML 文档的标签结构

find() 和 findAll()

  • findAll(tag, attrinutsd, recursive, text, limit, keywords)

  • find(tag, attributes, recursive, text, kewords)

参数解释

  • tag - 可以传入一个或者多个标签名称组成的列表来查找, 将返回所有的包含要查找的标签的列表集合

  • attributes - 传入一个字典格式的属性和属性对应的值{'class', 'green'}

  • recursive - 递归参数, 是一个布尔变量, 默认True , 会查找需要的子标签以及子标签的子标签, False 只会查找文档的一级标签

  • limit - 只用于 findAll 方法, 获取需要的前几项, 一般是按照页面的顺序来排序的

  • keyword - 指定关键字, 可以更加具体的指定属性的标签, 注意使用class 是会造成冲突

    • bsObj.findAll(id='text')

    • bsObj.findAll('', {'id', 'text'})

可以直接获取 bsObj 对象的标签

  • bsObj.div.h1 获取 h1 标签 - 只对 bsObj 有效

NavigableString对象用来表示标签里的文字

Comment 对象用来表示文档中的注释

2. 拿取元素

bsObj.div.findAll('img') 找出文档中的第一个 div 然后获取这个 div 中所有的后代中的 img 标签 列表

获取子标签

  
  # 获得表格中的所有的 子标签 (tr th td) 的内容
  for child in bsObj.find('table', {'id', 'goo'}).children:
      print(child)

兄弟标签

bsObj.next_siblings 下一个兄弟标签

bsObj.previous_silblings 上一个兄弟标签

父标签

bsObj.parent 父标签

正则表达式 + BeautiflSoup

[^a-z] 表示不匹配包含在 [ ]中的内容, 例为 不匹配a-z

?! 排除 也表示 不包含, 通常放在 字符或者 正则表达式的前面, 让后面的正则表达式 排除不包含的内容 例 ^(?![A-Z]).)*$ - 匹配.但不包含 A-Z

  
  import re
  
  from bs4 import BeautifulSoup
  
  
  ...
  bsObj = BeautifulSoup(html)
  images = bsObj.findAll("img", {"src", re.compile("\.\.\/img\/gifts/img.*\.jpg")})
  for image in images:
      print(iamge['src'])
      

获取属性

bsObj.attrs 获取全部属性, 得到的是一个字典

bsObj.attrs['src'] 获取 src 属性

Lambda 表达式

soup.findAll(lambda tag: len(tag.attrs) == 2) 获取满足 属性的个数是 2 的标签

BeautifulSoup的解析器

Python标准
  
  使用方法: BeautifulSoup(html_doc,"html.parser")
  
  优势:Python内置,执行速度适中,文档容错能力强
  
  劣势:Python 2.7.3 or 3.2.2) 的版本中文档容错能力差
  123456

lxml解析器(推荐使用)

  
  使用方法:BeautifulSoup(html_doc,'lxml')
  
  优势:速度快,文档容错能力强(C编写),推荐使用
  1234

html5lib

  
  使用方法:BeautifulSoup(html_doc,"html5lib")
  
  优势:最好的容错性,已浏览器的方式解析文档,生成Html5格式的文档
  
  劣势:速度慢,不依赖外部扩展

存储数据

mongodb

常用方法

  • 一般来说,我们创建集合用db.createCollection(name),如:db.createCollection("log"),创建一个名字为log的集合,没有任何的大小,数量限制,使用_id作为默认索引;

  • 限制集合空间的大小:db.createCollection("log",{size:1024})或db.createCollection("log",{capped:true,size:1024}),创建一个名字为log集合,限制它的空间大小为1M,如果超过1M的大小,则会删除最早的记录;

  • 限制集合的最大条数:db.createCollection("log",{max:1024}),创建一个名字为log集合,最大条数为1024条,超过1024再插入数据的话会删除最早的一条记录。这个不能使用capped:true,否则会报错;

  • 即限制最大条数有限制使用空间大小:db.createCollection("log",{size:1024,max:1024})或db.createCollection("log",{capped:true,size:1024,max:1024}),限制集合最大使用空间为1M,最大条数为1024条。

增删改查, 筛选

csv

  
  
  csvFile = open('editor.csv', 'wt', newline='', encoding='utf-8')
  writer = csv.writer(csvFile)
  
  
  writer.writerow(content)
  • 每一行都用一个换行符分隔

  • 列与列之间用逗号分隔(逗号分隔值)

图片

  
  
  from urllib.request import urlretrieve
  
  
  urlretrieve(url, 'pic.jpg')  # 保存文件 默认保存在当前文件夹, 也可以写绝对路径
  

多线程并发下载

多线程的使用

aiohttp

实现并发http请求

  
  
  import aiohttp
  
  
  async with aiohttp.ClientSession() as session:
      
      
  session   get post 
      

asyncio

asyncio的编程模式就是一个消息循环,我们从asyncio模块中直接获取一个 EventLoopd的引用, 然后把需要执行的协程扔到 EventLoop 中执行, 就实现了异步 IO

  
  
  from asyncio import 
  
  
  loop = asyncio.get_event_loop()
  task = asyncio.wait([self.get_html()])
  loop.run_until_complete(task)  # 执行函数
  loop.close()

消息队列-RobbitMQ (了解)

消息队列(Message Queue)是一种应用之间的通讯方式, 消息发送后可以立即返回, 由消息系统来确保消息的可靠传递。消息的发布者只需要将消息发布到 MQ 之中就行, 不用管是谁来获取消息, 消息的使用者值需要从 MQ 中拿取消息而不用在乎是谁发布符消息。这样发布者和使用者都不用知道对方是谁, 这样就可以将 两者之间 解耦合。

自动化测试工具 selenium


猜你喜欢

转载自blog.csdn.net/running987/article/details/81270645