爬虫入门(五)抓取网页数据

前面已经实现了获取整个网页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 html5lib

url = '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是最佳选择,因为该方法即快速又健壮

  • 9
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python爬虫入门教程是一份非常详细的教程,它可以帮助初学者了解Python爬虫的基本概念和技术。该教程包括了Python爬虫的基础知识、爬虫框架、爬虫实战案例等内容,让学习者能够快速掌握Python爬虫的核心技术和应用方法。此外,该教程还提供了大量的实例代码和实践指导,帮助学习者更好地理解和应用Python爬虫技术。总之,Python爬虫入门教程是一份非常实用和全面的教程,值得初学者认真学习和掌握。 ### 回答2: Python爬虫作为一种大数据采集和处理技术,已经被广泛应用于数据挖掘、商业智能、搜索引擎优化等领域。入门Python爬虫需要掌握以下技能: 1.基础Python编程知识 爬虫算法本身和平常写其他程序没有太大区别,入门爬虫需要先学习好基本Python编程知识,包括数据类型、流程控制、函数等。 2.了解HTML基础知识 在网页中,HTML是最基本的语言,而爬虫就是通过抓取HTML页面上的信息来达到采集的目的。入门爬虫需要至少需要掌握:HTML基本结构、标签、属性、类、id、常用标签等。 3.了解CSS选择器和XPATH 使用CSS选择器和XPATH可以更快、更准确地定位到要爬取的数据。入门爬虫需要至少了解CSS选择器和XPATH的基本语法和常用方式。 4.学会使用requests模块 在Python爬虫中,使用requests模块可以轻松获取URL页面,并提供一个response对象供处理。入门爬虫需要掌握requests的基本使用方法和参数含义。 5.使用BeautifulSoup模块 通过使用BeautifulSoup模块,可以方便快捷地解析HTML文档,从而可以轻松提取出需要采集的数据。入门爬虫需要掌握BeautifulSoup模块的基本语法和对象的方法。 6.了解常用的反爬虫技术 爬虫虽然可以方便地采集数据,但很多网站都设置了反爬虫机制,入门爬虫需要了解常用的反爬虫技术,如IP黑名单、用户代理伪装、验证码、动态加载等。 总的来说,Python爬虫的入门门槛并不高,只要了解基本编程知识,掌握少量HTML和CSS知识,学会使用requests和BeautifulSoup模块,以及了解一些常用的反爬虫技术,即可进行简单的爬虫开发。但随着爬虫的深入应用,还需要掌握更多的编程技巧和高级爬虫技术。 ### 回答3: Python爬虫是一种自动化获取互联网数据的方法,是数据挖掘和数据分析的一个重要组成部分。Python语言具有简洁、易上手的特点,成为了大量网络爬虫的首选语言之一。在本文中,我们将从以下几个方面介绍Python爬虫入门教程,希望能够帮助想要入门Python爬虫的人员快速上手。 一、爬虫所需Python库 1. requests库 requests库是Python中最常用的爬虫库,使用该库可以发送HTTP请求,获取与解析网页内容。使用该库可以发送HTTP/1.1和HTTP/2.0请求,自动进行参数编码,并支持上传文件、Cookies、HTTP认证等。 2. BeautifulSoup库 BeautifulSoup库可以将HTML文件解析成常规的Python对象,可以使用该库分析网页中的元素,容易实现xpath、CSS选择器等功能。 3. scrapy库 scrapy库是Python中最常用的爬虫框架,适用于大规模数据抓取。该框架支持多任务并发抓取,支持自定义中间件,具有强大的数据处理功能。 二、爬虫流程 Python爬虫流程如下: 1. 发送HTTP请求 使用requests库向目标网站发送HTTP请求,获取网页源代码。 2. 解析网页内容 使用BeautifulSoup库解析网页内容,使用xpath或CSS选择器提取所需数据。 3. 存储数据 使用数据库或文件将所需数据存储起来。 4. 设置爬虫策略 设置爬虫策略,包括访问间隔、网站深度等。 5. 点击下一页 通过解析html文件获取下一页的链接,不断点击下一页抓取更多数据。 三、爬虫实例 下面我们以一个爬取猫眼电影排行榜的爬虫为例,来介绍Python爬虫的实现过程。 首先我们需要导入requests库和BeautifulSoup库: ```python import requests from bs4 import BeautifulSoup ``` 然后我们需要发送HTTP请求,获取目标网站的网页源代码: ```python url = 'https://maoyan.com/board/4' header = { 'Referer': 'https://maoyan.com/board', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299' } response = requests.get(url, headers=header) ``` 接下来我们需要使用BeautifulSoup库解析网页内容: ```python soup = BeautifulSoup(response.content, 'html.parser') ``` 通过观察网页源代码,我们可以获取每个电影的信息块: ```python selector = 'dd' content = soup.select(selector) ``` 再解析每个信息块中的电影名称和电影评分: ```python for movie in content: name_selector = 'a > img' name = movie.select(name_selector)[0]['alt'] score_selector = 'p.score' score = movie.select(score_selector)[0].get_text() print(name + ',' + score) ``` 最后,我们就可以得到猫眼电影排行榜中每部电影的名称和评分了。 以上就是Python爬虫的入门教程,希望能够帮助想要学习Python爬虫的人员快速上手。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值