温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Python异步新闻爬虫之网络请求函数的优化案例

发布时间:2020-11-03 11:00:37 来源:亿速云 阅读:165 作者:小新 栏目:编程语言

这篇文章主要介绍Python异步新闻爬虫之网络请求函数的优化案例,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

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

问题我们前面已经描述清楚,解决的方法也有了,那就废话不多讲,代码立刻上(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()来输出异常,有助于我们发现更多问题。

以上是Python异步新闻爬虫之网络请求函数的优化案例的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI