古话有云“君子爱美”,身为七尺男儿,我当然是同一个德性。我不知道有多少人学习爬虫是从各个“色彩斑斓”的网站上爬取图片开始的,反正我是。当我开始我的爬虫之旅的时候,煎蛋网已经在高度戒备中,高手总是大有人在,“兵来将挡,水来土掩”,煎蛋对反爬虫的措施已经有了多种的应对方法。
关于爬虫,似乎是处于道德的“灰色地带”,很多网站对于爬虫的行为并不是很欢迎,虽然这并不能阻止我们的脚步,但是建议爬取一个网站之前看看网站的robots.txt文件,里面提供了爬虫的一些信息,诸如哪些行为是允许的、哪些行为是禁止的。我们既然爬虫,那我们就应该做一直有素养的虫虫,让我们的行为更加“取之有道”。
爬出的书籍,我推荐图灵丛书的《python网络数据采集》,封面是一只穿山甲而不是蜘蛛、甲虫之类爬虫动物,当你对着书封面发呆的时候,应该会有所思考吧。
我这里分享我第的一个爬虫,作为对自己生活的记录,同时,如果有人能够看到这篇文章,如果我能够给ta一点帮助,那就足够了。
用到的模块:
re模块:正则表达式
os模块:系统操作
urllib模块:只用到其中简单几个
BeautifulSoup:网页解析
time模块:可以用于休眠,限制爬虫爬得太厉害
关于正则表达式,常用的十二种符号和意义,(对于初学的我很有用):
===========================================================
1 * 匹配前面的字符、子表达式0次以上 a*b* aaaabb
2 + 匹配前面的字符、子表达式1次以上 a+b+ abbbb
3 [] 任选一个 [A-Z] C
4 () 表达式编组 (a*b)* aababb
5 {m,n} 匹配前面的字符、子表达式m到n次 a{3,5} aaaa
6 [^] 匹配一个不再括号内的字符 [^a-z] S
7 | 匹配任意一个由竖线分割的字符 a(b|c|d) ab,ac
8 . 匹配任意单个字符 b.d bad,bnd
9 ^ 指定开始的字符或者子表达式 ^a apple
10 \ 转义字符 \.\|\\ . |\
11 $ 末端匹配 [A-Z][a-z]$ Ab
12 ?! 不包含,如果要整个字符串加^..$ ^(?![A-Z].)*$ avvd,.b
=============================================================
第一步:踩点
第一步当然是踩点,除非你有明确的目的,我们的虫要去哪里,要去“偷”什么?
既然煎蛋强烈抵制爬虫,那我们绕路。额。。关于豆瓣的请不要害羞小组。。。好像美女也很多。
·观察网页
页面很干净很纯洁,但是点进来的时候似乎响应有点慢,看一下网页布局



很好,已经发现想要的了。
【鼻血】每页有十张图,从审查元素看到图片的src属性就是缩略图的地址,href是它的一个网页链接。
我们点击缩略图,弹出一个新的网页,只有少量东西加一张原图(好像原图也大部分不够清晰),从审查元素看到图片的src属性是图片的地址,但这和缩略图的地址很像,通过简单处理可以得到原图的链接而不用访问图片链接的网页。
点击下一页查看mm图,发现对应的网页只是在pages后面的数字不同而已,所以我们能够找到我们想要的页码了,也能找到相应页码内的链接了,所以开始动手吧。
程序开始载入需要的模块,由于本网页的内容比较简单我把re模块备注掉了,又由于本网站的下载速度。。。我把time模块备注了
import os from urllib.request import Request from urllib.request import urlopen from bs4 import BeautifulSoup #from time import sleep #import re
我们定义一个函数,用它来下载,输入的参数是m、n、下载文件夹的位置:
1 def dowmload_mm(m=1,n=2,path=dowmload_path): 2 3 img_links = find_img_m_n(m,n) 4 img_save(path,img_links)
此函数需要调用find_img_m_n()函数来获取所有图片的地址,然后调用img_save()来遍历下载链接来保存图片。
·find_img_m_n()函数是用来寻找m-n页中所有的链接,所以我写个寻找单页图片链接的函数,通过反复调用ta来达到目的。
def find_img_m_n(m,n): url_main = 'https://qingbuyaohaixiu.com/page/' print('给你搞第%d页到%d页的妹子图哦' %(m,n)) #递归所有链接 while m <= n: str_m = str(m) url = url_main + str_m find_img(url,links_count) print('第%d页链接保存完毕' %m) m += 1 return img_links
find_img()通过输入网址参数,使用urlopen()方法获取网页的request对象,我们在其中要加请求头来伪装成浏览器读取网页,通过beautifulsoup来读取img的src,去掉与原图网址不同的字符串,我的网速很快,但是读取网页的速度。。慢,运行程序是一个读取超时就可以使爬虫停在那里不动,需要设置超时,可以在urlopen时加入timeout,捕捉异常,我这里就让程序跳过,当然也可以选择多读取几次。
def find_img(url,links_count): req = url_header_maker(url) try: html = urlopen(req,timeout=3).read().decode("utf-8") except Exception as e: print(e) return None bsObj =BeautifulSoup(html,"lxml") links = bsObj.div.findAll('img') for link in links: if link not in img_links: link_t=link['src'] temp_list = link_t.split("-") img_url = temp_list[0]+'-'+temp_list[1]+'.jpg' img_links.append(img_url) links_count['count'] += 1 print('已添加了%d条妹图链接,莫急' %links_count['count'])
img_save(path,img_links)则要使用到os模块,检测文件夹是否存在,进行图片读取,同样要加请求头,不然。。403forbidden。
def img_save(path,img_links): if not os.path.exists(path): os.mkdir(path) for index,link in enumerate(img_links): print (link) req = url_header_maker(link) try: img = urlopen(req,timeout=5).read() with open(path+'/%s.jpg' %index,'wb') as f: f.write(img) print('pic %s downloaded' %index) except Exception as e: print(e) print("第%s张图片加载错误" %index) #sleep(3)
因为是自己写的程序,也比较粗糙,阅读起来可能不是非常有艺术感,但下了一千张图片感觉。。很满足。。。。。。。。。。
完整代码:
1 import os 2 from urllib.request import Request 3 from urllib.request import urlopen 4 from bs4 import BeautifulSoup 5 #from time import sleep 6 7 8 #弄个列表保存图片网址 9 img_links = [] 10 links_count ={'count':0} 11 dowmload_path = 'dowmloaded' 12 13 def url_header_maker(url): 14 head = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36\ 15 (KHTML, like Gecko)Chrome/49.0.2623.112 Safari/537.36'} 16 req = Request(url,headers=head) 17 return req 18 19 #收集一个页面的图片链接 20 def find_img(url,links_count): 21 22 req = url_header_maker(url) 23 try: 24 html = urlopen(req,timeout=3).read().decode("utf-8") 25 except Exception as e: 26 print(e) 27 return None 28 bsObj =BeautifulSoup(html,"lxml") 29 links = bsObj.div.findAll('img') 30 for link in links: 31 if link not in img_links: 32 link_t=link['src'] 33 temp_list = link_t.split("-") 34 img_url = temp_list[0]+'-'+temp_list[1]+'.jpg' 35 img_links.append(img_url) 36 links_count['count'] += 1 37 print('已添加了%d条妹图链接,莫急' %links_count['count']) 38 39 #收集m-n页的链接 40 def find_img_m_n(m,n): 41 url_main = 'https://qingbuyaohaixiu.com/page/' 42 print('给你搞第%d页到%d页的妹子图哦' %(m,n)) 43 #递归所有链接 44 while m <= n: 45 str_m = str(m) 46 url = url_main + str_m 47 find_img(url,links_count) 48 print('第%d页链接保存完毕' %m) 49 m += 1 50 return img_links 51 52 def img_save(path,img_links): 53 if not os.path.exists(path): 54 os.mkdir(path) 55 56 for index,link in enumerate(img_links): 57 print (link) 58 req = url_header_maker(link) 59 try: 60 img = urlopen(req,timeout=5).read() 61 with open(path+'/%s.jpg' %index,'wb') as f: 62 f.write(img) 63 print('pic %s downloaded' %index) 64 except Exception as e: 65 print(e) 66 print("第%s张图片加载错误" %index) 67 #sleep(3) 68 69 70 71 72 73 def dowmload_mm(m=1,n=2,path=dowmload_path): 74 75 img_links = find_img_m_n(m,n) 76 img_save(path,img_links) 77 78 79 if __name__=="__main__": 80 dowmload_mm(1,100)
-------------------------------------------------------------------------------------------------------------------------------------笔墨出租---------------------------------------------------------------------
浙公网安备 33010602011771号