最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 大规模异步新闻爬虫之网络请求函数的优化

    正文概述    2020-06-16   153

    大规模异步新闻爬虫之网络请求函数的优化

    前面我们实现了一个简单的再也不能简单的新闻爬虫,这个爬虫有很多槽点,估计大家也会鄙视这个爬虫。上一节最后我们讨论了这些槽点,现在我们就来去除这些槽点来完善我们的新闻爬虫。

    问题我们前面已经描述清楚,解决的方法也有了,那就废话不多讲,代码立刻上(Talk is cheap, show me the code!)。

    downloader 的实现

    import requests
    import cchardet
    import traceback
    
    
    def downloader(url, timeout=10, headers=None, debug=False, binary=False):
        _headers = {
            'User-Agent': ('Mozilla/5.0 (compatible; MSIE 9.0; '
                           'Windows NT 6.1; Win64; x64; Trident/5.0)'),
        }
        redirected_url = url
        if headers:
            _headers = headers
        try:
            r = requests.get(url, headers=_headers, timeout=timeout)
            if binary:
                html = r.content
            else:
                encoding = cchardet.detect(r.content)['encoding']
                html = r.content.decode(encoding)
            status = r.status_code
            redirected_url = r.url
        except:
            if debug:
                traceback.print_exc()
            msg = 'failed download: {}'.format(url)
            print(msg)
            if binary:
                html = b''
            else:
                html = ''
            status = 0
        return status, html, redirected_url
    
    
    if __name__ == '__main__':
        url = 'http://news.baidu.com/'
        s, html,lost_url_found_by_大大派 = downloader(url)
        print(s, len(html),lost_url_found_by_大大派)

    这个downloader()函数,内置了默认的User-Agent模拟成一个IE9浏览器,同时接受调用者自定义的headers和timeout。使用cchardet来处理编码问题,返回数据包括:

    状态码:如果出现异常,设置为0

    内容: 默认返回str内容。但是URL链接的是图片等二进制内容时,注意调用时要设binary=True

    重定向URL: 有些URL会被重定向,最终页面的url包含在响应对象里面

    新闻URL的清洗

    我们先看看这两个新闻网址:

    http://xinwen.eastday.com/a/n181106070849091.html?qid=news.baidu.com
    http://news.ifeng.com/a/20181106/60146589_0.shtml?_zbs_baidu_news

    上面两个带?的网站来自百度新闻的首页,这个问号?的作用就是告诉目标服务器,这个网址是从百度新闻链接过来的,是百度带过来的流量。但是它们的表示方式不完全一样,一个是qid=news.baidu.com, 一个是_zbs_baidu_news。这有可能是目标服务器要求的格式不同导致的,这个在目标服务器的后台的浏览统计程序中可能用得到。

    然后去掉问号?及其后面的字符,发现它们和不去掉指向的是相同的新闻网页。

    从字符串对比上看,有问号和没问号是两个不同的网址,但是它们又指向完全相同的新闻网页,说明问号后面的参数对响应内容没有任何影响。

    正在抓取新闻的大量实践后,我们发现了这样的规律:

    新闻类网址都做了大量SEO,它们把新闻网址都静态化了,基本上都是以.html, .htm, .shtml等结尾,后面再加任何请求参数都无济于事。

    但是,还是会有些新闻网站以参数id的形式动态获取新闻网页。

    那么我们抓取新闻时,就要利用这个规律,防止重复抓取。由此,我们实现一个清洗网址的函数。

    g_bin_postfix = set([
        'exe', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx',
        'pdf',
        'jpg', 'png', 'bmp', 'jpeg', 'gif',
        'zip', 'rar', 'tar', 'bz2', '7z', 'gz',
        'flv', 'mp4', 'avi', 'wmv', 'mkv',
        'apk',
    ])
    
    g_news_postfix = [
        '.html?', '.htm?', '.shtml?',
        '.shtm?',
    ]
    
    
    def clean_url(url):
        # 1. 是否为合法的http url
        if not url.startswith('http'):
            return ''
        # 2. 去掉静态化url后面的参数
        for np in g_news_postfix:
            p = url.find(np)
            if p > -1:
                p = url.find('?')
                url = url[:p]
                return url
        # 3. 不下载二进制类内容的链接
        up = urlparse.urlparse(url)
        path = up.path
        if not path:
            path = '/'
        postfix = path.split('.')[-1].lower()
        if postfix in g_bin_postfix:
            return ''
    
        # 4. 去掉标识流量来源的参数
        # badquery = ['spm', 'utm_source', 'utm_source', 'utm_medium', 'utm_campaign']
        good_queries = []
        for query in up.query.split('&'):
            qv = query.split('=')
            if qv[0].startswith('spm') or qv[0].startswith('utm_'):
                continue
            if len(qv) == 1:
                continue
            good_queries.append(query)
        query = '&'.join(good_queries)
        url = urlparse.urlunparse((
            up.scheme,
            up.netloc,
            path,
            up.params,
            query,
            ''  #  crawler do not care fragment
        ))
        return url

    清洗url的方法都在代码的注释里面了,这里面包含了两类操作:

    判断是否合法url,非法的直接返回空字符串

    去掉不必要的参数,去掉静态化url的参数

    网络爬虫知识点

    1. URL清洗

    网络请求开始之前,先把url清洗一遍,可以避免重复下载、无效下载(二进制内容),节省服务器和网络开销。

    2. cchardet 模块

    该模块是chardet的升级版,功能和chardet完全一样,用来检测一个字符串的编码。由于是用C和C++实现的,所以它的速度非常快,非常适合在爬虫中用来判断网页的编码。

    切记,不要相信requests返回的encoding,自己判断一下更放心。上一节,我们已经列举了一个例子来证明requests对编码识别的错误,如果忘了的话,可以再去回顾一下。

    3. traceback 模块

    我们写的爬虫在运行过程中,会出现各种异常,而且有些异常是不可预期的,也不知道它会出现在什么地方,我们就需要用try来捕获异常让程序不中断,但是我们又需要看看捕获的异常是什么内容,由此来改善我们的爬虫。这个时候,就需要traceback模块。

    比如在downloader()函数里面我们用try捕获了get()的异常,但是,异常也有可能是cchardet.detect()引起的,用traceback.print_exc()来输出异常,有助于我们发现更多问题。


    起源地下载网 » 大规模异步新闻爬虫之网络请求函数的优化

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元