python网络爬虫——初识

对目标站点的规模和结构进行一定程度的了解
1.检查robots.txt:可以让爬虫了解爬取该网站时存在哪些限制;
2.检查网站地图:网站提供Sitemap文件可以帮助爬虫定位网站最新的内容,而无需爬取每一个网页;
3.估计网站大小;可以通过Google搜索的site关键词过滤域名结果;
4.网站所用技术:构件网站所用的技术也会对我们的爬虫产生影响,可以使用builtwith这个工具,它可以检查网站构件的技术类型。
安装工具

这里写代码片

pip install builtwith

以URL作为参数,下载该URL并对其进行分析,返回该网站所用的技术
>>> import builtwith
>>> builtwith.parse('http://example.webscraping.com')
{'web-servers': ['Nginx'], 'web-frameworks': ['Web2py', 'Twitter Bootstrap'], 'programming-languages': ['Python'], 'javascript-frameworks': ['jQuery', 'Modernizr', 'jQuery UI']}

可以看出示例网站使用了Python的Web2py框架,还是用了Twitter Bootstrap框架等信息。
5.寻找网站所有者
我们可以使用WHOIS协议查询域名的注册者是谁。Python中有一个针对该协议的封装库。
安装

pip install python-whois

返回结果

>>> import whois
>>> print(whois.whois('appspot.com'))
{
  "domain_name": [
    "APPSPOT.COM",
    "appspot.com"
  ],
  "registrar": "MarkMonitor, Inc.",
  "whois_server": "whois.markmonitor.com",
  "referral_url": null,
  "updated_date": [
    "2018-02-06 10:30:28",
    "2018-02-06 02:30:29-08:00"
  ],
  "creation_date": [
    "2005-03-10 02:27:55",
    "2005-03-09 18:27:55-08:00"
  ],
  "expiration_date": [
    "2019-03-10 01:27:55",
    "2019-03-09 00:00:00-08:00"
  ],
  "name_servers": [
    "NS1.GOOGLE.COM",
    "NS2.GOOGLE.COM",
    "NS3.GOOGLE.COM",
    "NS4.GOOGLE.COM",
    "ns3.google.com",
    "ns2.google.com",
    "ns1.google.com",
    "ns4.google.com"
  ],
  "status": [
    "clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited",
    "clientTransferProhibited https://icann.org/epp#clientTransferProhibited",
    "clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited",
    "serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited",
    "serverTransferProhibited https://icann.org/epp#serverTransferProhibited",
    "serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited",
    "clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)",
    "clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)",
    "clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)",
    "serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)",
    "serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)",
    "serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)"
  ],
  "emails": [
    "abusecomplaints@markmonitor.com",
    "whoisrelay@markmonitor.com"
  ],
  "dnssec": "unsigned",
  "name": null,
  "org": "Google LLC",
  "address": null,
  "city": null,
  "state": "CA",
  "zipcode": null,
  "country": "US"
}

编写第一个爬虫

常见的三种方法:

  • 爬取网站地图;
  • 便利每个网页数据库ID;
  • 跟踪网页连接

重试下载

import urllib2


#使用递归,如果出错最多访问两次,如果没有访问到就返回None;否则返回页面内容
def download(url,num_retries=2):
    print 'Downloading:',url

    try:
        html=urllib2.urlopen(url).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

download('http://httpstat.us/500')

这里写图片描述
设置用户代理
默认情况下,urllib2使用Python-urllib/2.7作为用户代理下载页面内容,我嫩可以使用可辨识的用户代理‘wswp’;

def download(url,user_agent='wswp',num_retries=2):
    print 'Downloading:',url
    headers={'User-agent':user_agent}
    request=urllib2.Request(url,headers=headers)
    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 crawl_sitemap(url):
    sitemap=download(url)
    links=re.findall('<loc>(.*?)</loc>',sitemap)

    for link in links:
        html=download(link)


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

这里写图片描述
ID遍历爬虫
我们将利用网站结构的弱点 , 更加轻松地访问有内容。

  • http:IIexample.webscraping.com/view/Afghanistan- 1
  • http:IIexample.webscraping.com/view/Australia-2
  • http:IIexample.webscraping.com/view/Brazil-3
    这些URL只在结尾处有区别,包括国家名和ID,在URL中包含别名的做法是非常普遍的,可以对搜索引擎优化起到帮助作用。一般情况下,Web服务器会忽略这个字符串,只使用ID来匹配数据库的相关记录。
import itertools

max_errors=5
num_errors=0

for page in itertools.count(1):
     url='http://example.webscraping.com/view/-%d' %page
     html=download(url)
     if html is None:
         num_errors+=1
         if num_errors==max_errors:
             break
     else:
         num_errors=0

五次重试下载后退出
链接爬虫
通过跟踪所有链接的方式,我们可以很容易地下载整个网站 的页面。但是,这种方法会下载大量我们并不需要的网页。例如, 我们想要从一个在线论坛中抓取用户账号详情页, 那么此时我们只需要下载 账号页, 而不需要下载讨论贴的页面。

#可以传入一个URL和指定的正则模式,只匹配需要的网站
def link_crawler(seed_url,link_regex):

    crawl_queue=[seed_url]
    #创建集合,用来存放已经访问过的链接
    seen=set(crawl_queue)
    while crawl_queue:
        url=crawl_queue.pop()
        html=download(url)
        for link in get_links(html):
            if re.search(link_regex,link):
                #创建绝对链接的形式,urllib 2无法获知上下文,所以相对链接无法工作
                link=urlparse.urljoin(seed_url,link)
                #避免有的两个链接相互链接使爬虫循环访问
                #创建集合seen,如果已经访问的就不再加入
                if link not in seen:
                    # seen[link]=depth+1
                    crawl_queue.append(link)
                    seen.add(link)
def get_links(html):
    webpage_regx=re.compile('<a[^>]+href=["\'](.*?)["\']',re.IGNORECASE)
    return webpage_regx.findall(html)

这里写图片描述

高级功能

解析robots.txt
我们需要解析 robots. t xt 文件,以避免下载禁止 爬取的URL。使用Python自带的 robotp arser 模块, 就可以轻松完成这项工作。

import robotparser
#robotparser模块首先加载robots.txt文件
rp=robotparser.RobotFileParser()
rp.set_url('http://example.webscraping.com/robots.txt')
rp.read()

url='http://example.webscraping.com'
user_agent='BadCrawler'
#can_fetch确定指定的用户代理是否允许访问网页
rp.can_fetch(user_agent,url)

支持代理
有时我们需要使用代理访问某个网站 。比如,Net flix 屏蔽美国以外的大多数国家 。使用urlli b2支持代理并没 有想象中 那么容易( 可以尝试使用更友好的 Python HTTP模块re que sts来实现该功能。

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

下载限速
如果我们爬取网站的速度过快,就会 面临被 封 禁或是造成服务器过载的风
险。为了降低这些风险, 我们可以在两次下载之间添加延 时, 从而对爬虫限
速。

Throttle类记录了每个域名上次访问的时间,如果当前时间距离上次
访问的时间小于延迟,则执行睡眠操作。

class Throttle:

    def __init__(self,delay):
        self.delay=delay
        self.domains={}

    def wait(self ,url):
        #urlparse.urlparse将url地址拆成六个部分,netloc为域名服务器,也可能包含用户信息
        domain=urlparse.urlparse(url).netloc
        last_accessed=self.domains.get(domain)

        if self.delay >0 and last_accessed is not None:
            sleep_secs=self.delay-(datetime.datetime.now()-last_accessed).seconds
            if sleep_secs>0:
                time.sleep(sleep_secs)

        #更新上一次访问时间
        self.domains[domain]=datetime.datetime.now()

我们 可以在每 次下载之前调用Throttle对爬虫进行限速。
避免爬虫陷阱
我们的爬虫会跟踪所有之前没有访问过的链接 。但是, 一些网站会动态生成页面内容, 这样就会出现无限多的网 页 。 比如, 网 站 有一个在线日历功能, 提供了可以 访问 下个月和下 一年的链接, 那么下个月的页面中 同样会包含访问 再下个月的 链接, 这样页面就会无止境地 链接 下去。 这 种情况被
称为爬虫陷阱
想要避免陷入爬虫 陷阱,一个简单的方 法是记录到达当前网页经过了多少个 链接, 也就是 深度。 当到达最大深度时, 爬虫就 不再向队列中添加该网页
中的链接了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值