用python写一个网络爬虫

一、引言与前期准备

1.1 深入了解一个网站的方法

检查robots.txt(了解抓取该网站时存在哪些限制)
检查sitemap(一般在robots.txt中能找到,这里提供了该网站的所有网页的链接)
估算网站大小(一个简便方法是检查Google爬虫的结果 -> site:www.baidu.com)
识别网站所用技术(python中的builtwith方法 -> builtwith.parse("www.baidu.com") )
寻找网站所有者(whois查询:站长或者python中的 -> print(whois.whois("www.baidu.com"))  )
 

1.2 网页访问error异常问题

在访问网页时,有时遇到网页访问出错(可能请求错误、可能服务端错误)从而为导致无法正常下载网页,因此我们要能健壮地捕获访问过程的错误并作出相应处理。这里转载一篇python3中的urllib.error实现: Python3网络爬虫(三):urllib.error异常。自己根据这篇文章及实际python3中遇到的问题成功实现了正常捕获网页访问error异常。以下代码实现两个功能:遇到5xx错误重试下载;设置用户代理
 
#此代码实现并测试爬取下载网页中的几个问题或方法:遇到5xx错误重试下载;设置用户代理
import urllib.request
import urllib.error
def download(url, user_agent = "brain", num_retries = 2):  #下载网页
    print("downloading:",url)
    header = {"user-agent": user_agent} #设置用户代理,而不使用python默认的用户代理Python-urllib/3.6
    req = urllib.request.Request(url, headers = header)
    try:
        html = urllib.request.urlopen(req).read()
    except urllib.error.URLError as e:    #下载过程中出现问题
        print("download error:",e.reason)
        html = None


        if num_retries > 0:     #错误4XX发生在请求存在问题,而5XX错误则发生在服务端存在问题,所以在发生5XX错误时重试下载
            if hasattr(e, "code") and 500<= e.code <600:
                return  download(url, user_agent, num_retries-1)  # recursively retry 5XX HTTP errors
    return html
#download("http://example.webscraping.com") #访问正常
download("http://httpstat.us/500") #这个网页测试用,一直是5XXerror

运行结果:

downloading: http://httpstat.us/500
download error: Internal Server Error
downloading: http://httpstat.us/500
download error: Internal Server Error
downloading: http://httpstat.us/500
download error: Internal Server Error

二、爬取网站

爬取网站,我们通常需要做两件事:下载网页(该过程一般称为爬取 crawling);提取数据(或保存数据,或继续分析数据等)

2.1 下载网页(爬取 crawling)

三种爬取网站的常见方法:爬取网站地图、遍历每个网页的数据库ID、跟踪网页链接

2.1.1  爬取网站地图sitemap中的url链接(使用正则表达式)

#def download()实现并测试爬取下载网页中的几个问题或方法:遇到5xx错误重试下载;设置用户代理
#def crawl_sitemap(url)实现爬取一个网站sitemap中url数据(用到正则表达式),并且将每个url下载

import urllib.request
import urllib.error
import re
def download(url, user_agent = "brain", num_retries = 2):  #下载url网页
    print("downloading:",url)
    header = {"user-agent": user_agent} #设置用户代理,而不使用python默认的用户代理Python-urllib/3.6
    req = urllib.request.Request(url, headers = header)
    try:
        html = urllib.request.urlopen(req).read()
    except urllib.error.URLError as e:    #下载过程中出现问题
        print("download error:",e.reason)
        html = None

        if num_retries > 0:     #错误4XX发生在请求存在问题,而5XX错误则发生在服务端存在问题,所以在发生5XX错误时重试下载
            if hasattr(e, "code") and 500<= e.code <600:
                return  download(url, user_agent, num_retries-1)  # recursively retry 5XX HTTP errors
    return html
#download("http://example.webscraping.com") #访问正常
#download("http://httpstat.us/500") #这个网页测试用,一直是5XXerror

def crawl_sitemap(url):  ##爬取一个网站sitemap中url,此url为网站sitemap的url
    sitemap = download(url)  # download the sitemap file
    sitemap = str(sitemap)   #把bytes类型转成str类型,以便下面用正则表达式提取数据
    links = re.findall("<loc>(.*?)</loc>", sitemap)  # extract the sitemap links这里用了正则表达式,返回的是结果列表
    for link in  links:
        html = download(link) #把爬取的url都下载下来

crawl_sitemap("http://example.webscraping.com/sitemap.xml")

2.1.2  ID遍历爬虫

我们无法完全依靠文件提供的url链接,当结果不符合预期(sitemap本身提供的链接有问题)或需求有变时,我们将不再依赖sitemap而转而利用网站结构的弱点更加轻松地访问所有内容。
http://example.webscraping.com/view/Brazil-3
http://example.webscraping.com/view/ Australia-2
可以看出上述url只在结尾处有区别,包括国家名和ID。一般情况下,web服务器会忽略这个字符串,只使用ID来匹配数据库中的相关记录。因此下面我们将其移除,加载:http://example.webscraping.com/view/3,测试发现链接可用能正常打开。因此现在我们忽略页面别名而直接使用ID来下载所有国家的页面
#def download()实现并测试爬取下载网页中的几个问题或方法:遇到5xx错误重试下载;设置用户代理
#def crawl_sitemap(url)实现爬取一个网站sitemap中url数据(用到正则表达式),并且将每个url下载

import urllib.request
import urllib.error 
import re #正则表达式
import itertools #使用ID遍历
def download(url, user_agent = "bra
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值