爬虫原理:
以下来自知乎解释
首先你要明白爬虫怎样工作。
想象你是一只蜘蛛,现在你被放到了互联“网”上。那么,你需要把所有的网页都看一遍。怎么办呢?没问题呀,你就随便从某个地方开始,比如说人民日报的首页,这个叫initial pages,用$表示吧。
在人民日报的首页,你看到那个页面引向的各种链接。于是你很开心地从爬到了“国内新闻”那个页面。太好了,这样你就已经爬完了俩页面(首页和国内新闻)!暂且不用管爬下来的页面怎么处理的,你就想象你把这个页面完完整整抄成了个html放到了你身上。
突然你发现, 在国内新闻这个页面上,有一个链接链回“首页”。作为一只聪明的蜘蛛,你肯定知道你不用爬回去的吧,因为你已经看过了啊。所以,你需要用你的脑子,存下你已经看过的页面地址。这样,每次看到一个可能需要爬的新链接,你就先查查你脑子里是不是已经去过这个页面地址。如果去过,那就别去了。
好的,理论上如果所有的页面可以从initial page达到的话,那么可以证明你一定可以爬完所有的网页。
想象你是一只蜘蛛,现在你被放到了互联“网”上。那么,你需要把所有的网页都看一遍。怎么办呢?没问题呀,你就随便从某个地方开始,比如说人民日报的首页,这个叫initial pages,用$表示吧。
在人民日报的首页,你看到那个页面引向的各种链接。于是你很开心地从爬到了“国内新闻”那个页面。太好了,这样你就已经爬完了俩页面(首页和国内新闻)!暂且不用管爬下来的页面怎么处理的,你就想象你把这个页面完完整整抄成了个html放到了你身上。
突然你发现, 在国内新闻这个页面上,有一个链接链回“首页”。作为一只聪明的蜘蛛,你肯定知道你不用爬回去的吧,因为你已经看过了啊。所以,你需要用你的脑子,存下你已经看过的页面地址。这样,每次看到一个可能需要爬的新链接,你就先查查你脑子里是不是已经去过这个页面地址。如果去过,那就别去了。
好的,理论上如果所有的页面可以从initial page达到的话,那么可以证明你一定可以爬完所有的网页。
链接:http://www.zhihu.com/question/20899988/answer/24923424
1.爬取一个匿名可访问upload目录的网站
import re,os import urllib.request import urllib import ssl ssl._create_default_https_context = ssl._create_unverified_context from collections import deque queue = deque() visited = set() origurl=url = \'http://www.***.cn/Upload/\' # 入口页面, 可以换成别的 path = \'C:/Users/Administrator/Desktop/a/\' queue.append(url) cnt = 0 while queue: url = queue.popleft() # 队首元素出队 print(\'已经抓取: \' + str(cnt) + \' 正在抓取 <--- \' + url) cnt += 1 try: urlop = urllib.request.urlopen(url, timeout=3) except: continue if \'image\' in urlop.getheader(\'Content-Type\'): xpath=url.replace(origurl,\'\') orig_list=xpath.split("/") orig_ext_file = orig_list[-1] path_sub = orig_list[:-1] new_path=path+(\'/\'.join(path_sub)) try: os.makedirs(new_path) except Exception as e: print(e) urllib.request.urlretrieve(url, new_path+\'/\'+orig_ext_file) if \'html\' not in urlop.getheader(\'Content-Type\'): continue # 处理异常 try: data = urlop.read().decode(\'utf-8\') except: continue # 正则表达 提取页面中所有队列, and判断or访问过, too加入待爬队列 linkre = re.compile(\'href="(.+?)"\') for x in linkre.findall(data): if re.match(r"\?C=.", x): continue if re.match(r"/Upload/", x): continue if x not in visited: queue.append(url + x) visited |= {url} # 标记为已访问 print(\'加入队列 ---> \' + x)
2.抓取一个美图高清壁纸网站
import re import urllib.request import urllib import ssl ssl._create_default_https_context = ssl._create_unverified_context # 取消ssl验证https:// from collections import deque queue = deque() visited = set() website = \'http://www.***.com/\' website_column = \'column/\' url = website + website_column + \'80827.html\' # 入口页面 path = \'./images/\' queue.append(url) # 加入队列 cnt = 0 while queue: url = queue.popleft() # 队首元素出队 visited |= {url} # 已访问 print(\'已经抓取: \' + str(cnt) + \' 正在抓取 <--- \' + url) cnt += 1 try: urlop = urllib.request.urlopen(url, timeout=3) except: continue current_num_re = re.compile(r\'/\' + website_column + \'(\d+)/\') current_num = current_num_re.findall(url) if url == website + website_column: continue if \'html\' not in urlop.getheader(\'Content-Type\'): continue # 处理异常 try: data = urlop.read().decode(\'gbk\') except: try: data = urlop.read().decode(\'utf-8\') except: continue # 正则表达 提取页面中所有队列, and判断or访问过, too加入待爬队列 linkre = re.compile(\'href="(.+?)"\') inside1 = re.compile(r\'/\' + website_column + \'(.*)\') inside2 = re.compile(r\'(\d+).htm\') for x in linkre.findall(data): if \'http\' not in x and x not in visited: resulturl = \'\' c = inside1.findall(x) if c: resulturl = website + website_column + c[0] else: c = inside2.findall(x) if c: cnum = \'\' cnum = current_num[0] if current_num else \'\' resulturl = website + website_column + cnum + \'/\' + c[0] + \'.htm\' if resulturl: queue.append(resulturl) print(\'加入队列 ---> \' + resulturl) linkrerr = re.compile(\'<p><img src="(.*)" onload="btnaddress\(1\);\') src = linkrerr.findall(data) if src: print(src) req = urllib.request.Request(src[0], headers={ \'Connection\': \'Keep-Alive\', \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\', \'Accept-Language\': \'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3\', \'User-Agent\': \'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko\', \'Referer\': url }) resource = urllib.request.urlopen(req, timeout=30) orig_list = src[0].split("/") orig_ext_file = orig_list[-1] path_sub = orig_list[:-1] # urllib.request.urlretrieve(src[0], path + orig_ext_file) #网站拒绝爬虫使用Referer 时, urlretrieve无法下载 foo = open(path + orig_ext_file, "wb") str = resource.read() foo.write(str) foo.close()
参考地址: https://jecvay.com/2014/09/python3-web-bug-series1.html