初级爬虫使用指北(4)--解析网页

目录

  1. 目的
  2. 网页构成
  3. 获取标签里的信息
  4. 解析网页的一般流程
  5. 完整代码
  6. 附加题

1. 目的

当获取到指定网页文件(html源代码)后,下一步工作即是要提取出其中所需要的信息。程序的优势在于可以“不知疲倦地”完成某些重复性的工作——这意味着当需求是获取某些具有规律性的重复性的结构化网页时(例如目标网页们都长的差不多),可以让爬虫根据一些 固定规则 抽取网页上的信息。

这一节即是关于如何编写 固定规则 的内容。


2. 网页构成:定位,定位,再定位!

回忆上一节中我获取的网页的数据,我将它打印到屏幕上了,那就像右侧的样子,我想获取的只是这其中很小的一部分信息。

在屏幕中打印网页

Chrome浏览器
所以,我开始利用浏览器的辅助工具帮我在这些数据中找到我需要的信息。
使用Chrome浏览器,在页面上点击右键(Mac触摸板 两只手指按下去),点击“检查”功能。

分析国民级网站-百度一下

“检查”功能
浏览器就会出现“检查”对应的功能板。
现在我想提取百度首页右上角的栏目信息,包括栏目名称和对应的链接(图中左侧的红色方框),这些信息存储在网页对应的标签信息中(图中右侧的红色方框)。

Chrome浏览器-"检查"功能

HTML标签
可以通过以下的标签顺序提取出这些信息,例如,“新闻”。


3. 获取标签里的信息:你猜我会怎么提取目标信息

使用爬虫解析网页数据,获取目标信息

"""
上一节中我们是这样做的
data = requests.get("www.baidu.com", headers=headers)
print(data.text)
让我们继续
"""
from bs4 import BeautifulSoup

html =  data.content
soup = BeautifulSoup(html,'lxml')
titles = soup.select("div#wrapper > div#head > div.head_wrapper > div#u1 > a.mnav")
titles[0].get_text
titles[0].get("href")

对比目标信息的标签,有什么发现吗?

当然有!

BeautifulSoup是什么?
美丽汤是一个Python用于解析网页的包,记得在命令行中使用pip3 install bs4进行预先安装。

使用美丽汤解析网页后,必须使用soup来命名生成的对象吗?
要是心情不好,我可能就直接s = BeautifulSoup(html,'lxml')


4. 解析网页的一般流程

使用爬虫获取目标信息的过程一般可以包括这些:

  • 使用浏览器“检查”功能定位目标信息(初级爬虫使用指北 (4) 第二节)
  • 使用爬虫获取网页数据(初级爬虫使用指北 (3) )
  • 使用爬虫解析网页数据,获取目标信息(初级爬虫使用指北 (4) 第三节)

5. 完整代码

现在我来完成一次获取网页+解析网页的过程。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Jul 25 13:15:14 2018

@author: alfonso
"""
# ------- obtain html data 指北(3)
import requests
url = 'http://www.baidu.com'
headers = {
    'User-Agent': 'Chrome/53.0.2785.143',
    'Connection': 'keep-alive',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
}
html = requests.get(url, headers=headers)  # 这里我改变了一个变量名称
# ------- mining html 指北(4)
# 1. 导入相关包
from bs4 import BeautifulSoup

# 2. 使用 BeautifulSoup 解析网页
soup = BeautifulSoup(html.content, 'lxml')

# 3. 使用CSS选择器,传入解析规则
titles = soup.select(
    "div#wrapper > div#head > div.head_wrapper > div#u1 > a.mnav")

# 4. 打印出自己所需的信息
print("先看看一共获取到了哪些数据")
print(titles)
print() # 打印一个空行,作用类似于留空一行
print("获取一个标题试试")
print(titles[0].get_text)
print()
print("获取这个标题对应的链接试试")
print(titles[0].get("href"))
print()
运行后的样子

6. 附加题

美丽汤的功能非常强大,如果你真有兴趣的话,可以百度一下它的官方文档(应该有中文版的),或者看看以下我的笔记。
网页源代码


相关BeautifulSoup操作

  • 节点选择器
  • 方法选择器
  • CSS选择器

Let's go

  • 节点选择器
# coding:utf-8
from bs4 import BeautifulSoup
"""
使用 div.text # 
"""
soup = BeautifulSoup(html,'lxml')

news_titles = soup.select("div.text > em.f14 > a.linkto")# 使用select选择器,返回一个列表,包括所有符合的元素
news_titles[0].get_text() # "台拟将蔡英文贺岁春联“自自冉冉”一词列入辞典"
news_titles[0].get("href") # "http://news.qq.com/a/20170104/000968.htm"

'''
a1 > a2 父节点为a1的所属有a2元素
a1#nodeID, 选择  
a1[nodeID], 选择  
其他参见https://cuiqingcai.com/5476.html
'''

## 名称 name
soup.title.name # title 利用name属性获取节点的名称

## 属性 attrs
print(soup.p.attrs) #{'class': ['title'], 'name': 'dromouse'}
print(soup.p.attrs['name']) #dromouse

## 获取内容 string
print(soup.p.string) # 利用string属性获取节点元素包含的文本内容

## 关联
### 子孙节点
soup.p.contents #返回结果是列表形式,得到的结果是直接子节点的列表

soup.p.children # 返回结果是生成器
for i, child in enumerate(soup.p.children): 
    print(i, child)

# contents 和 children 作用相同

# 获得所有子孙节点
soup.p.descendants# 返回结果是生成器
for i, child in enumerate(soup.p.descendants):
    print(i, child)

### 祖先节点
soup.a.parent # 获取直接父节点,生成器类型 
soup.a.parents # 所有祖先节点,生成器类型 
# 用列表输出了它的索引和内容
print(list(enumerate(soup.a.parents)))

### 兄弟节点
print('Next Sibling', soup.a.next_sibling)
print('Prev Sibling', soup.a.previous_sibling)
print('Next Siblings', list(enumerate(soup.a.next_siblings)))
print('Prev Siblings', list(enumerate(soup.a.previous_siblings)))
'''
next_sibling和previous_sibling分别获取节点的下一个和上一个兄弟元素,next_siblings和previous_siblings则分别返回所有前面和后面的兄弟节点的生成器。
'''
  • 方法选择器
## 方法选择器
find_all(name , attrs , recursive , text , **kwargs)
# name = 'ul' 'li' 等标签名称
# attrs = 字典型 {'id': 'list-1'}
# 也可以直接使用一些常见的属性
'''
print(soup.find_all(id='list-1'))
print(soup.find_all(class_='element'))
'''

# text 参数可用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式对象

print(soup.find_all(text=re.compile('link')))

'''
find相关的方法
find_parents()和find_parent():前者返回所有祖先节点,后者返回直接父节点。
find_next_siblings()和find_next_sibling():前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点。
find_previous_siblings()和find_previous_sibling():前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点。
find_all_next()和find_next():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。
find_all_previous()和find_previous():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。
'''
  • CSS选择器
# 使用CSS选择器
#需要调用select()方法,传入相应的CSS选择器
print(soup.select('.panel .panel-heading'))
print(soup.select('ul li'))
print(soup.select('#list-2 .element'))
print(type(soup.select('ul')[0]))

#节点类型是Tag类型,所以获取属性还可以用原来的方法
for ul in soup.select('ul'):
    print(ul['id'])
    print(ul.attrs['id'])
    print('Get Text:', ul.get_text()) # 效果与.string一样
    print('String:', ul.string) #

你可能感兴趣的:(初级爬虫使用指北(4)--解析网页)