关于爬虫学习的一点心得分享

Posted on 2018-01-05 00:55  林良煌  阅读(1396)  评论(0)    收藏  举报

    古话有云“君子爱美”,身为七尺男儿,我当然是同一个德性。我不知道有多少人学习爬虫是从各个“色彩斑斓”的网站上爬取图片开始的,反正我是。当我开始我的爬虫之旅的时候,煎蛋网已经在高度戒备中,高手总是大有人在,“兵来将挡,水来土掩”,煎蛋对反爬虫的措施已经有了多种的应对方法。

    关于爬虫,似乎是处于道德的“灰色地带”,很多网站对于爬虫的行为并不是很欢迎,虽然这并不能阻止我们的脚步,但是建议爬取一个网站之前看看网站的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)
完整代码自用

-------------------------------------------------------------------------------------------------------------------------------------笔墨出租---------------------------------------------------------------------