《用python写网络爬虫》--网页抓取方法

本文介绍了如何使用Python进行网页抓取,包括正则表达式、BeautifulSoup模块的方法。针对正则表达式的优点和局限性,文章提出BeautifulSoup作为更方便的网页解析工具,并给出了具体使用示例。最后,讨论了在链接爬虫中添加抓取回调函数以实现对多个网站的爬取。
摘要由CSDN通过智能技术生成

目标:

掌握三种网页抓取的方法:正则表达式、BeautifulSoup模块,lxml模块

1.正则表达式

首先确定目标网页:http://example.webscraping.com/view/United-Kingdom-239,抓取目标:网页中的面积数据

import urllib
from urllib.request import urlopen
import re
import urllib.error
def download(url):
    print('Downloading:',url)
    try:
        request=urllib.request.Request(url)
        response=urllib.request.urlopen(request)
        html=response.read().decode('utf-8')
    except urllib.error.URLError as e:
        print('Download error:',e.reason)
        html=None
    return html
url='http://example.webscraping.com/view/United-Kingdom-239'
html=download(url)
# print(html)
pattern=re.findall('<td class="w2p_fw">(.*?)</td>',html)
print(pattern)

这样的代码得到的部分结果是:
['<img src="/places/static/images/flags/gb.png" />', '244,820 square kilometres', '62,348,447', 'GB', 'United Kingdom', 'London', '<a href="/continent/EU">EU</a>', '.uk', 'GBP', 'Pound', '44', '@# #@@|@## #@@|@@# #@@

可以看到多个国家属性都用到了'<td class="w2p_fw">标签,要想分离出面积属性,我们可以只选择其中的第二个元素,如下所示:
pattern=re.findall('<td class="w2p_fw">(.*?)</td>',html)[1]

此时得到的结果:
244,820 square kilometres

虽然现在可以使用这个方案,但是如果网页发生变化,该方案很可能就会失效。比如表格发生了变化,去除了第二行中的国土面积数据。如果我们只是现在抓取数据,就可以忽略这种未来可能发生的变化,但是,如果我们希望未来还能再次抓取该数据,就需要给出更加健壮的解决方案,从而尽可能避免这种布局变化所带来的问题。想要该正则表达式更加健壮, 我们可以将其父元素<tr>也加入进来。由于该元素具有ID属性,所以应该是唯一的。

pattern=re.findall('<tr id="places_area__row">.*?<td class="w2p_fw">(.*?)</td>',html)

可以得到相同的结果

虽然这个正则表达式更容易适应未来的变化,但又存在着难以构造、可读性差的问题,此外,还有一些微小的布局变化也会使该正则表达式无法满足,过于脆弱,所以接下来介绍另外两种网页抓取的方法。

2.Beautiful Soup

Beautiful Soup是一个非常流行的Python模块。该模块可以解析网页,并提供定位内容的便捷接口。

使用Beautiful Soup的第一步是将已下载的HTML内容解析为soup文档。由于大多数网页都不具备良好的HTML格式,因此Beautiful soup需要对其实际格式进行确定。举个例子,用Beautiful Soup来解析属性值两侧引号缺失和标签未闭合的问题。

from bs4 import BeautifulSoup
broken_html='<ul class=country><li>Area<li>Population</ul>'
#解析HTML
soup=BeautifulSoup(broken_html,'lxml')
fixed_html=soup.prettify()
#可以用prettify实现格式化输出,使HTML标准
print(fixed_html)


运行结果:



<html>
 <body>
  <ul class="country">
   <li>
    Area
   </li>
   <li>
    Population
   </li>
  </ul>
 </body>
</html>

从上面的执行结果我们可以看出,Beautiful Soup能够正确解析缺失的引号并闭合标签,此外还添加了<html>和<body>标签使其成为完整的HTML文档。现在可以使用find()和find_all()方法来定位我们需要的元素了。

from bs4 import BeautifulSoup
broken_html='<ul class=country><li>Area<li>Population</ul>'
#解析HTML
soup=BeautifulSoup(broken_html,'lxml')
fixed_html=soup.prettify()
#可以用prettify实现格式化输出,使HTML标准
ul=soup.find('ul',attrs={'class':'country'})
print(ul.find('li'))
#打印出了匹配的第一个
print(ul.find_all('li'))
#打印出了所有匹配到的
#运行结果
<li>Area</li>
[<li>Area</li>, <li>Population</li>]

#接下来,我们使用这个方法来抽取示例国家面积的完整数据:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值