jiguangdongtaiip

我们需要让爬虫从每个网页中抽取一些数据,然后实现某些事情,这种做法被称为数据抓取
分析网页
查看网页源代码,使用Firebug Lite扩展,Firebug是Joe Hewitt开发的一套与Firefox集成在一起的功能强大的web开发工具,可以实时编辑、调试和监测任何页面的CSS、HTML和JavaScript。在这里用于网页源代码的查看。
安装Firebug Lite,下载Firebug Lite的包,然后再浏览器中安装这个插件。
三种网页抓取的方法
正则表达式、BeatifulSoup模板、强大的lxml模块
正则表达式

def download(url,user_agent=\'wswp\',proxy=None,num_retries=2):
    print \'Downloading:\',url
    headers={\'User-agent\':user_agent}
    request=urllib2.Request(url,headers=headers)

    opener=urllib2.build_opener()
    if opener:
        proxy_params={urlparse.urlparse(url).scheme:proxy}
        opener.add_handler(urllib2.ProxyHandler(proxy_params))

    try:
        html=urllib2.urlopen(request).read()
    except urllib2.URLError as e:
        print \'Download:\' ,e.reason
        html=None
        if num_retries>0:
            if hasattr(e,\'code\') and 500 <=e.code<600:
                return download(url,num_retries-1)

    return html

def get_links(html):
    webpage_regx=re.compile(\'<a[^>]+href=["\\'](.*?)["\\']\',re.IGNORECASE)
    # webpage_regx=re.compile(,re.IGNORECASE)
 link_list1=webpage_regx.findall(html)
    link_list2=[]
    for link in link_list1:
        if re.search(\'/view/\',link):
            link_list2.append(link)
    return link_list2

import re

url=\'http://example.webscraping.com/view/United-Kingdom-239\'
html=download(url)

for link in get_links(html):
    link = urlparse.urljoin(url, link)
    areas=download(link)
    # print areas
    #匹配国家面积
    context=re.findall(r\'<td class="w2p_fw">(.*?)</td>\',areas)[1]
    print context

 运行结果:

 

正则表达式提供了抓取数据的快捷方式,但是该方法过于脆弱,容易在网页更新后出现问题。
Beautful Soup
Beautful Soup是一个非常流行的Python模块。该模块可以解析网页,并提供定位内容的便捷接口。
安装

 pip install beautifulsoup4 --user

使用第一步:将已经下载的HTML内容解析为soup文档。
使用find或者find_all方法获取.
Lxml
基于libxml2这一XML解析库的Python封装.该模块使用C编写,解析速度更快.
第一步:将有可能步合法的HTML解析为统一格式.

import lxml.html

broken_html=\'<ul class=country><li>Area<li>Population</ul>\'
tree=lxml.html.fromstring(broken_html)
fixed_html=lxml.html.tostring(tree,pretty_print=True)

print fixed_html

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

测试三种方法的性能

import re
import urllib2
import urlparse
from bs4 import BeautifulSoup
import lxml.html
import time

#
#
#
#获取网页内容
def download(url,user_agent=\'wswp\',proxy=None,num_retries=2):
    print \'Downloading:\',url
    headers={\'User-agent\':user_agent}
    request=urllib2.Request(url,headers=headers)

    opener=urllib2.build_opener()
    if opener:
        proxy_params={urlparse.urlparse(url).scheme:proxy}
        opener.add_handler(urllib2.ProxyHandler(proxy_params))

    try:
        html=urllib2.urlopen(request).read()
    except urllib2.URLError as e:
        print \'Download:\' ,e.reason
        html=None
        if num_retries>0:
            if hasattr(e,\'code\') and 500 <=e.code<600:
                return download(url,num_retries-1)

    return html

#使用正则表达式匹配
def re_scraper(html):
    results={}
    results[\'area\']=re.search(\'<tr id="places_area__row">.*?<td class="w2p_fw">(.*?)</td>\',html).groups()[0]
    return results
#使用BeautifulSoup匹配
def bs_scraper(html):
    soup=BeautifulSoup(html)
    results={}
    results[\'area\']=soup.find(\'table\').find(\'tr\',id=\'places_area__row\').find(\'td\', class_=\'w2p_fw\').string

    return results

#使用cssselect选择器匹配
def lxml_scraper(html):
    tree=lxml.html.fromstring(html)
    results={}
    conf=tree.cssselect(\'table > tr#places_area__row > td.w2p_fw\')[0].text_content()
    results[\'area\']=conf

    return results
#计算获取时间
#每个网站爬取的次数
NUM_ITERATIONS=1000
html=download(\'http://example.webscraping.com/places/default/view/Afghanistan-1\')
for name,scraper in [(\'Re\',re_scraper),(\'Bs\',bs_scraper),(\'Lxml\',lxml_scraper)]:

    #开始的时间
    start=time.time()
    for i in range(NUM_ITERATIONS):
        if scraper==re_scraper:
#默认情况下,正则表达式模块会缓存搜索结果,为了使对比条件更一致,re.purge()方法清除缓存
            re.purge()
        result=scraper(html)
        #检查结果
        assert(result[\'area\']==\'647,500 square kilometres\')

    #结束时间
    end=time.time()

    print \'%s: %.2f seconds\' %(name,end-start)

结果分析:
由于lxml和正则表达式都是用C语言写的,所以效果比用Python写的BeautifulSoup要好.由于lxml在搜索之前必须输入解析为内部格式,所以会产生额外的开销.而爬取同一网页时这种开销会降低.
方法总结

抓取方法 -性能- 使用难度 -安装难度
正则表达式- 快 -困难- 简单(内置)
Beautiful Soup -慢 -简单- 简单(纯python)
Lxml 快 -简单 -相对困难

如果是下在网页,而不是抽取数据的话,那么使用Beautiful Soup,如果只需抓取少量数据,并且避免额外依赖的话,选择正,通常情况下使用lxml比较合适.

 

分类:

技术点:

相关文章: