前面已经实现了获取整个网页HTML的功能,并且在获取HTML的基础上,加上一些诸如:下载出错自动重试、用户代理、服务器代理、爬取深度、避免重爬、id遍历、链接遍历等进阶功能。而且在处理过程中也初步使用了正则表达式。

但是前面我们获取的HTML中的数据很多,其中大部分是我们不需要的。因此在本节中,我们要介绍对比三种抓取数据的方式,也可以叫选择器,并给出他们的性能对比,以供选择。

1.分析网页

在抓取一个网页之前的具体内容之前,我们首先应该分析一下网页的结构。网页的构成是一种标签化的结构语言编写的。这些标签也可以看成一个个元素,比如标题元素、表单元素、表格元素、行元素、列元素。通常我们要抓取的数据就在这些元素内。

通过F12或者右键查看页面源码,通过审查元素找到我们感兴趣的内容

以示例网站为例,打开日本的网页地址:

http://example.python-scraping.com/places/default/view/Japan-108

按F12打开开发者工具,元素审查,找到自己感兴趣的内容,比如日本的面积、简称、语言等,

发现这些元素位于一个表单form内,<tr>行标签内的<td>列元素,进一步发现<tr>有ID属性,<td>有class属性 通过这两个字段就可以精确定位到某行某列。

2.抓取方式一正则表达式

正如前面编写链接爬虫时那样,使用正则表达式匹配页面内容不失为一个好的方式,阅读编写正则表达式是一个爬虫程序员必备的技能

2.1本例中用到的匹配规则如下:

\b 匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。

例如:

“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”;

“\b1_”可以匹配“1_23”中的“1_”,但不能匹配“21_3”中的“1_”。

r'':Python中字符串前面加上 r 表示原生字符串(rawstring)。不使用r,那么匹配时候需要4个反斜杠,正则需要转化一次,python解释器需要转化一次,使用r就不用使用转义字符

如: >>> re.findall("abc\b","adsssa abc ")                 输出:[]

>>> re.findall(r"abc\b","adsssa abc ")               输出:['abc']

在页面截图中,可以看到数据列

查看元素发现他们储存在class="w2p_fw的<td>中的 </td><td class="w2p_fw">377,835 square kilometres</td>

因此构造一个正则表达式r'<td class="w2p_fw">(.*?)</td>'可以完整匹配出所要的内容

假如想精准定位日本的人口,定位id为places_population__row的<tr>标签元素的html格式如下

<tr id="places_population__row"> <td class="w2p_fl"> <label class="readonly" for="places_population" id="places_population__label">Population: </label> </td> <td class="w2p_fw">127,288,000 </td> <td class="w2p_fc"> </td> </tr>

因为网站有可能单引号双引号混用,或者多按了两个空格,因此引号用['"]匹配,空格用/s*匹配,最终构造的正则式为: r'<tr id=['"]places_population__row['"]>.*?<td\s*class=['"]w2p_fw['"]>(.*?)</td>'

import re
from scrap_01 import GetData            #该文件为在前两章中编写的获取网页HTML的方法
url = 'http://example.python-scraping.com/places/default/view/Japan-108'
html = GetData(url)
data = re.findall(r'<td class="w2p_fw">(.*?)</td>',html)
print(data)
data2 = re.findall('''<tr id=['"]places_population__row['"]>.*?<td\s*class=['"]w2p_fw['"]>(.*?)</td>''',html)
print(data2)

3.抓取方式一Beautiful Soup

从上个例子可以得出正则表达式存在这一定的缺点,如正则式难以构造、可读性差等 不过我们还有其他的库可以用,比如流行的BeautifulSoup和强大的lxml模块。

3.1安装:pip install beautifulsoup4

3.2使用步骤:

1.将获得的HTML文档解析为soup文档

Beautiful Soup能对一些不规范编写HTMl格式的文档进行修正,如标签闭合,属性值引号缺失

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

#'html.parser'是BeautifulSoup默认的解析器,有时并不怎么好用,修正Html的能力有限。

这里推荐使用html5lib或者lxml(下文中介绍)

soup = BeautifulSoup(html, 'html5lib')

2.使用find或者findall方法来定位元素

find('tag','regex'),tag指标签类型,regex可以是attrs属性字典或者正则表达式,返回的是html形式的元素标签<class 'bs4.element.Tag'>

find_all('tag','regex'),返回的是元素标签集合<class 'bs4.element.ResultSet'>

td = soup.find('tr', attrs={'ID':'places_population__row'}) print(td.find('td'))

print(td.find('td').text)

3.获取标签内的文本

对于就是标签内只有不含有其他标签子节点,那么这个 tag 可以使用 result.string 得到文本,也可以用 result.text 获得文本 如果 tag 包含了多个子节点,tag 就无法确定 result.string 方法应该调用哪个子节点的内容, result.string 的输出结果是 None

from bs4 import BeautifulSoup
import html5liburl = 'http://example.python-scraping.com/places/default/view/Japan-108'
html = GetData(url)
soup = BeautifulSoup(html, features="html5lib")
tr = soup.find(attrs={'id':'places_population__row'})       #find()返回的是html形式的元素标签<class 'bs4.element.Tag'>
print(tr)
td = tr.find_all(attrs={'class':'w2p_fw'})                  #find_all返回的是元素标签集合<class 'bs4.element.ResultSet'>
print(td)
print(td[0].text)

4.抓取方式一Lxml

xml是XML和HTML的解析器,其主要功能是解析和提取XML和HTML中的数据; lxml和正则一样,也是用C语言实现的,是一款高性能的python HTML、XML解析器,也可以利用XPath语法,来定位特定的元素及节点信息 在解析HTML代码的时候,如果HTML代码不规范或者不完整,lxml解析器会自动修复或补全代码,从而提高效率

4.1解析器解析html

lxml通常都是用etree解析,这里用的是是lxml.html,其实etree功能更多,lxml.html专解析html,二者解析html的结果相差不大

lxml.html:

import lxml.html html = lxml.html.fromstring(sample)

result2 = lxml.html.tostring(html,pretty_print =True)

print(result2)

etree:

from lxml import etree html = etree.HTML(sample)

result1 = etree.tostring(html,pretty_print =True)

print(result1)

附结构化输出概念: python中的pprint模块负责以合适的格式打印便于阅读的行块。它使用换行和缩进以明确的方式打印数据。 “pprint”模块它将对象格式化为可读的格式,每行都有适当的宽度。它带有可调节的宽度限制,以使它更容易为用户。 它将所有元素转换为可以用Python常量表示的字符串,并以美观的格式打印它们。pprint函数返回可以在解释器中作为输入运行的输出。 而且,通过解析字符串更容易将其转换回该类型。

pprint的使用方法:

import pprint

#使用.pprint()对象或实例化我们自己的pprint对象PrettyPrinter()。

pprint.pprint(['Radha', 1, 'Hari', 'Simesh', 25, 847])

my_pprint = pprint.PrettyPrinter()

my_pprint.pprint(['Radha', 1, 'Hari', 'Simesh', 25, 847])

而在解析器lxml.html.tostring(html,pretty_print =True)中的pretty_print =True表达的即是要格式化输出 的意思

4.2.选择(定位)元素

选择的方法包括有:

XPath选择器、find()方法或者CSS选择器。

这里使用的是CSS选择器,因为它更加简介,并且能解析动态内容。

安装:pip install cssselect

使用:

几个常用的选择器:

*:通用选择器

X:元素选择器

#X:ID选择器

.X:类选择器

X Y:后代选择器

X > Y:子元素选择器

X[title]:简单属性选择器

X[href="foo"]:精准属性值选择器

X[href*="xxx"]:匹配部分属性值选择器

X[href^="http"]:匹配属性值开头的选择器

X[href$=".jpg"]:匹配属性值结尾的选择器

X[data-*="foo"]:自定义属性选择器

参考链接:https://blog.csdn.net/Ed7zgeE9X/article/details/102812665

故我们所要构造的选择器:

tr#places_population__row > td.w2p_fw

意思为选择id为places_population__row的tr元素的子元素中类Class=w2p_fw的元素

from lxml.html import fromstring,tostring
import cssselect
url = 'http://example.python-scraping.com/places/default/view/Japan-108'
html = GetData(url)
tree = fromstring(html)
td = tree.cssselect('tr#places_population__row > td.w2p_fw')[0]
print(type(td))
population = td.text_content()
print(population)

4.3使用控制台+jQuery测试CSS选择器

jquery是一个优秀的javascript的轻量级框架,兼容css3和各大浏览器。 Jquery就是1个js文件,只不过它对JS进行了简化。

jQuery 库包含以下特性:

HTML 元素选取

HTML 元素操作

CSS 操作

HTML 事件函数

JavaScript 特效和动画

HTML DOM 遍历和修改

AJAX Utilities

在浏览器的开发者工具中的控制台上可以测试自己编写的CSS选择器

$()或jQuery() 称之为jq选择器环境,在里面加上引号填写相关选择器即可,就可以获取匹配的元素。

4.4XPath选择器

CSS无法应对HTML非常不完整或者存在格式不当的问题时,这时CSS选择器可能会无法工作,尽管在解析时已经尽最大的努力修复html了, 但还是有很大的可能无法工作。这种情况下XPath可以帮助你基于页面的层次结构关系构建非常明确的选择器。

XPath选择器:

选取节点:
表达式       描述                        示例              结果
nodename   选取此节点的所有子节点            body           选取 body 元素的所有子节点
/          从根节点选取                 /html          选取根元素 html
//         匹配选择的当前节点,不考虑位置    //img          选取所有 img 元素,而不管它们在文档的位置
.          选取当前节点                 ./img          选取当前节点下的 img 节点
..         选取当前节点的父节点         ../img         选取当前节点的父节点下的 title
@          选取属性                       //a[@href=”image1.html”]   选取所有 href 属性为 “image1.html” 的 a 节点
                                        //a/@href       获取所有 a 节点的 href 属性的值
使用谓词:
谓语用来查找某个特定的节点或者包含某个指定的值的节点,谓语嵌在方括号中。
路径表达式                  结果
//body//a[1]               选取属于 body 子元素的第一个 a 元素
//body//a[last()]          选取属于 body 子元素的最后一个 a 元素
//a[@href]                 选取所有拥有名为 href 的属性的 a 元素
//a[@href=’image2.html’]   选取所有 href 属性等于 “image2.html” 的 a 元素

常用函数:
contains(s1,s2)             如果s1中包含s2,返回True,否则返回False
text()                      获取文本内容
starts-with()               从起始位置匹配字符串

参考链接:https://blog.csdn.net/qq_32942549/article/details/78400675

url = 'http://example.python-scraping.com/places/default/view/Japan-108'
html = GetData(url)
tree = fromstring(html)
population = tree.xpath('//tr[@id="places_population__row"]/td[@class="w2p_fw"]/text()')[0]
print(population)

4.5lxml和家族树
家族树就是html文档的dom树,lxml提供了访问网页中元素父亲、兄弟、孩子元素的方法
方式:
获取元素对象
table = tree.xpath('//table')[0]
1.得到孩子元素
    table.getchildren()
2.得到前一个兄弟元素
    table.getprevious()
3.得到后一个兄弟元素
    table.getnext()
4.得到父元素
    table.getparent()

5.性能对比

由于lxml和re正则是用C语言写的,而BeautifulSoup是用python写的
所以理论上来说BeautifulSoup的速度是相对要慢的多的
抓取方式          性能          使用难度            安装难度
正则表达式         快           困难                简单(内置模块)
BeautifulSoup    慢            简单                简单(纯python)
Lxml             快            简单                相对困难(3.9以后版本也简单)
因此通常情况下lxml是最佳选择,因为该方法即快速又健壮

爬虫入门(五)抓取网页数据相关推荐

  1. 【php网页爬虫】php抓取网页数据

    插件介绍: PHP Simple HTML DOM解析类:Simple HTML DOM parser 帮我们很好地解决了使用 php html 解析 问题.可以通过这个php类来解析html文档,对 ...

  2. python爬网页数据用什么_初学者如何用“python爬虫”技术抓取网页数据?

    原标题:初学者如何用"python爬虫"技术抓取网页数据? 在当今社会,互联网上充斥着许多有用的数据.我们只需要耐心观察并添加一些技术手段即可获得大量有价值的数据.而这里的&quo ...

  3. Python 爬虫篇#笔记02# | 网页请求原理 和 抓取网页数据

    目录 一. 网页请求原理 1.1 浏览网页的过程 1.2 统一资源定位符URL 1.3 计算机域名系统DNS 1.4 分析浏览器显示完整网页的过程 1.5 客户端THHP请求格式 1.6 服务端HTT ...

  4. 逆向爬虫18 Scrapy抓取全站数据和Redis入门

    逆向爬虫18 Scrapy抓取全站数据和Redis入门 一.全站数据抓取 1. 什么是抓取全站数据? 我们曾经在过猪八戒,图片之家,BOSS直聘等网站,利用网站官方提供的搜索功能,搜索指定关键词的内容 ...

  5. Python爬虫之XPath基础教程:用代码抓取网页数据

    Python爬虫之XPath基础教程:用代码抓取网页数据 在网络时代,网页数据是获取信息和进行分析的最重要的来源之一.Python的爬虫技术让我们可以轻松抓取网页数据,并进行数据处理.XPath是一种 ...

  6. node爬虫,抓取网页数据

    node爬虫,抓取网页数据 1.什么是爬虫? 抓取信息或者数据的程序或者是脚本 2.通过node实现对网页数据的抓取. 安装插件 request,处理请求(此包以被弃用) npm i request ...

  7. cookie追加数据_集算器 SPL 抓取网页数据

    [摘要] 集算器 SPL 支持抓取网页数据,根据抓取定义规则,可将网页数据下载到在本地进行统计分析.具体定义规则要求.使用详细情况,请前往乾学院:集算器 SPL 抓取网页数据! 网站上的数据源是我们进 ...

  8. 【.NET】使用HtmlAgilityPack抓取网页数据

    原文:[.NET]使用HtmlAgilityPack抓取网页数据 刚刚学习了XPath路径表达式,主要是对XML文档中的节点进行搜索,通过XPath表达式可以对XML文档中的节点位置进行快速定位和访问 ...

  9. python 抓取网页数据

    python 抓取网页数据 此文解决如何从不同网页爬取数据的问题及注意事项,重点说明requests库的应用. 在开始之前,要郑重说明一下,不是每一个网页都可以爬取数据哦.有的网页涉及个人隐私或其他敏 ...

  10. excel数据自动录入网页_Excel自动抓取网页数据,数据抓取一键搞定

    网站上的数据源是我们进行统计分析的重要信息源.我们在生活中常常听到一个词叫"爬虫",能够快速抓取网页上的数据,这对于数据分析相关工作来说极其重要,也是必备的技能之一.但是爬虫大多需 ...

最新文章

  1. eas账号是什么意思_刚开始做抖音带货和好物推荐,如何布局抖音种草账号矩阵?...
  2. 【Qt】解决在linux上使用Qt的媒体模块(Qt += multimedia)缺少模块multimedia的问题
  3. 使用Application.GetResourceStream从XAP安装包加载任意资源
  4. Flutter之第一个 Flutter App(四)
  5. 数据结构与算法 —— 二叉树
  6. K8s 从懵圈到熟练 – 镜像拉取这件小事
  7. 410. Split Array Largest Sum 分割数组的最大值
  8. Redis设计与实现笔记
  9. python队列精灵对战_python队列Queue
  10. 常用的loss函数,以及在训练中的使用
  11. Linux学习第三步(Centos7安装mysql5.7数据库)
  12. javaweb框架--自定义标签与freemaker结合
  13. docker搭建pxc集群
  14. 想找一些设计素材不知道去哪里找?
  15. ic卡c语言程序,sle4442程序(ic卡程序,C语 - 控制/MCU - 电子发烧友网
  16. [USACO09NOV]Job Hunt
  17. 给自己职业发展的建议
  18. 信用卡不激活到底会怎样?会有哪些负面影响呢?
  19. Cadence Allegro PCB添加泪滴的方法
  20. 移动WEB各种布局开发笔记

热门文章

  1. vue音乐播放器之入门篇
  2. Google Nexus 7 二代 刷入 Kail Net Hunter 过程记录!!!
  3. 升级到win11家庭版了
  4. worker服务器推送消息,浏览器中serviceWorker用法
  5. 如何学习新概念英语第四册
  6. 功率半导体器件中的米勒效应(Miller Effect)
  7. 【测试沉思录】22. 前端性能测试怎么做?
  8. 用虚拟打印机实现文档格式的转换
  9. 大学英语四六级证有多大用?要不要考?
  10. Qt官方示例-速度仪表盘