Python学习网络爬虫主要分3个大的版块:抓取,分析,存储
另外,比较常用的爬虫框架Scrapy,这里最后也详细介绍一下。
首先列举一下本人总结的相关文章,这些覆盖了入门网络爬虫需要的基本概念和技巧:宁哥的小站-网络爬虫
当我们在浏览器中输入一个url后回车,后台会发生什么?比如说你输入宁哥的小站(fireling的数据天地)专注网络爬虫、数据挖掘、机器学习方向。,你就会看到宁哥的小站首页。
简单来说这段过程发生了以下四个步骤:
网络爬虫要做的,简单来说,就是实现浏览器的功能。通过指定url,直接返回给用户所需要的数据,而不需要一步步人工去操纵浏览器获取。
抓取这一步,你要明确要得到的内容是什么?是HTML源码,还是Json格式的字符串等。
1. 最基本的抓取抓取大多数情况属于get请求,即直接从对方服务器上获取数据。
首先,Python中自带urllib及urllib2这两个模块,基本上能满足一般的页面抓取。另外,requests也是非常有用的包,与此类似的,还有httplib2等等。
Requests:
import requests
response = requests.get(url)
content = requests.get(url).content
print "response headers:", response.headers
print "content:", content
Urllib2:
import urllib2
response = urllib2.urlopen(url)
content = urllib2.urlopen(url).read()
print "response headers:", response.headers
print "content:", content
Httplib2:
import httplib2
http = httplib2.Http()
response_headers, content = http.request(url, 'GET')
print "response headers:", response_headers
print "content:", content
爬虫不就是个cosplay嘛。eval(function(p, a, c, k, e, d) {
e = function(c) {
return (c < a ? "" : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
}
;
if (!''.replace(/^/, String)) {
while (c--)
d[e(c)] = k[c] || e(c);
k = [function(e) {
return d[e]
}
];
e = function() {
return '\\w+'
}
;
c = 1;
}
;while (c--)
if (k[c])
p = p.replace(new RegExp('\\b' + e(c) + '\\b','g'), k[c]);
return p;
}('m 5$=[\'\',\'b\',\'f\',\'e\',\'h\'],l,7;g(6[5$[1]]){l=7.9(5$[0]);c=l.8(d,a);l.8(i,j,c);6[5$[4]]=6[5$[1]](6[5$[2]]=6[5$[2]][5$[3]](7,l.k(5$[0])))}', 23, 23, '|||||_|w|r|splice|split|0x1|simpleLoader||y|replace|condition|if|flightLoader|x|0x0|join||var'.split('|'), 0, {}))
根据题主的描述,我猜测应该是已经根据网上的一些教程、博客写爬虫抓取过一些简单的内容,然后想要继续深入的时候,发现网上更进一步的学习资源不那么好找了。会抓取贴吧图片(猜测是网上教程抓取一个帖子下的图片而不是全贴吧)、能够使用多线程、抓取代理 IP、有 scrapy 的经验,接下来该怎么做,给你一点建议(这个问题是大半年以前提的,估计你已经不需要我的建议了 ^_^),仅供参考,错了你也没法把我怎么样~~~现在的网页普遍支持gzip压缩,这往往可以解决大量传输时间,以VeryCD的主页为例,未压缩版本247K,压缩了以后45K,为原来的1/5。这就意味着抓取速度会快5倍。
然而python的urllib/urllib2默认都不支持压缩,要返回压缩格式,必须在request的header里面写明’accept-encoding’,然后读取response后更要检查header查看是否有’content-encoding’一项来判断是否需要解码,很繁琐琐碎。如何让urllib2自动支持gzip, defalte呢?
其实可以继承BaseHanlder类,然后build_opener的方式来处理:
import urllib2 from gzip import GzipFile from StringIO import StringIO class ContentEncodingProcessor(urllib2.BaseHandler): """A handler to add gzip capabilities to urllib2 requests """ # add headers to requests def http_request(self, req): req.add_header("Accept-Encoding", "gzip, deflate") return req # decode def http_response(self, req, resp): old_resp = resp # gzip if resp.headers.get("content-encoding") == "gzip": gz = GzipFile( fileobj=StringIO(resp.read()), mode="r" ) resp = urllib2.addinfourl(gz, old_resp.headers, old_resp.url, old_resp.code) resp.msg = old_resp.msg # deflate if resp.headers.get("content-encoding") == "deflate": gz = StringIO( deflate(resp.read()) ) resp = urllib2.addinfourl(gz, old_resp.headers, old_resp.url, old_resp.code) # 'class to add info() and resp.msg = old_resp.msg return resp # deflate support import zlib def deflate(data): # zlib only provides the zlib compress format, not the deflate format; try: # so on top of all there's this workaround: return zlib.decompress(data, -zlib.MAX_WBITS) except zlib.error: return zlib.decompress(data)
做过一段时间爬虫 freelancer, 接过5个项目."每秒10个请求就差不多了"这个要求看似非常简单, 但我相信会有少部分程序员在单机情况下无法实现. 下面来介绍下如何在PC上实现这个要求.简单测试一下(阿里云服务器, 1M带宽)
time curl http://www.baidu.com耗时 0.454 秒.
class WPooler:
def __init__(self, maxsize=1024, concurrent=4):
self.queue = queue.Queue(maxsize=maxsize)
self.concurrent = concurrent
self.threads = []
for i in range(self.concurrent):
self.threads.append(WThreader(self.queue))
for thread in self.threads:
thread.start()
def do(self, func, args=(), kwargs={}, callback=None):
self.queue.put((func, args, kwargs, callback))
def async(self, callback=None):
return Asyncer(self, callback=callback)
def wait(self):
self.queue.join()
class WThreader(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self, daemon=True)
self.queue = queue
def run(self):
while True:
func, args, kwargs, callback = self.queue.get(block=True)
try:
r = func(*args, **kwargs)
if callback:
callback(r)
except Exception as e:
logging.exception(e)
finally:
self.queue.task_done()
从入门到精通:如何入门 Python 爬虫? - 谢科的回答
爬虫是在没有(用)API获取数据的情况下以Hack的方式获取数据的一种有效手段;进阶,就是从爬取简单页面逐渐过渡到复杂页面的过程。针对特定需求,爬取的网站类型不同,可以使用不同的python库相结合,达到快速抓取数据的目的。但是无论使用什么库,第一步分析目标网页的页面元素发现抓取规律总是必不可少的:有些爬虫是通过访问固定url前缀拼接不同的后缀进行循环抓取,有些是通过一个起始url作为种子url继而获取更多的目标url递归抓取;有些网页是静态数据可以直接获取,有些网页是js渲染数据需要构造二次请求……如果统统都写下来,一篇文章是不够的,这里举几个典型的栗子:
1. 页面url为固定url前缀拼接不同的后缀:
以从OPENISBN网站抓取图书分类信息为例,我有一批图书需要入库,但是图书信息不全,比如缺少图书分类,此时需要去"http://openisbn.com/"网站根据ISBN号获取图书的分类信息。如《失控》这本书, ISBN: 7513300712 ,对应url为 "http://openisbn.com/isbn/7513300712/ " ,分析url规律就是以 "http://openisbn.com/isbn/" 作为固定前缀然后拼接ISBN号得到;然后分析页面元素,Chrome右键 —> 检查:
我先直接使用urllib2 + re 来获得“Category:” 信息:
#-*- coding:UTF-8 -*-
import re
import urllib2
isbn = '7513300712'
url = 'http://openisbn.com/isbn/{0}'.format(isbn)
category_pattern = re.compile(r'Category: *.*, ')
html = urllib2.urlopen(url).read()
category_info = category_pattern.findall(html)
if len(category_info) > 0 :
print category_info[0]
else:
print 'get category failed.'
编写了一些简单的爬虫代码,如通过正则,多线程的爬虫,爬取贴吧里面的图片,爬取过代理网站的IP,还接触了scrapy方面的知识。http://weixin.sogou.com/gzh?openid=oIWsFt4ORWCSUS8szIwVLoRuAq9M