python爬虫实践(一)

概述:

        第一次接触爬虫,从简单一点的爬取百度图片开始,话不多说,直接上手。

前期准备:

        首先要配置环境,这里使用到的是 requests第三方库,相比 Beautifulsoup而言requests是个比较轻便的库包。
        1.requests安装:
        在cmd里将目录切换到你的pip所在路径。比如我的在E:\Python\Python36\Scripts这个目录下,先切换到E盘,再进入这个路径( 或者更简单,直接找到这个根目录,按shift鼠标右键,直接打开cmd

pip install requests
出现下图则安装成功


        2.requests使用:

        简单介绍一下requests的常用方法,基本知道一个requests.get()和requests.post()就行了。requests的返回值可以有多种形式输出,最常用的是".text"和".content",前者输出unicode,后者输出二进制。其他方法忘了可以查手册:requests快速上手

        3.python正则模块使用:

        python的正则模块是re,这里主要用到的函数是:

findall(pattern,str,re.S)

(re.S的意思是让"."可以匹配换行符,不然有些标签头和尾是分几行的,就会匹配失败)

        正则表达式用到的是:

(.*?)

        ( ):表示这个内容是我们需要提取的

         .*:表示匹配任意字符0-n次

        ?:表示非贪心,找到第一个就停下来

分析网页:

        首先打开百度图片,输入我们想搜索的图片


        点击搜索


        按F12打开开发者工具,

        1.点击开发者工具左上角的鼠标跟随;

        2.鼠标移动到图片点击;

        3.复制开发者工具里图片的地址。


        在网页空白处,鼠标右键点击查看网页源代码

        Ctrl+F打开搜索框,粘贴刚刚复制的图片地址


        找到图片地址,发现有四个地址thumbURL,middleURL,hoverURL,objURL,我们用哪个呢,通过打开网页发现,objURL是最清晰的,所以我们选择用objURL(其他几个也行)



编写代码:

        我们要用到2个包,一个是正则(re),一个是requests包

#-*- coding:utf-8 -*-
import re
import requests

        复制搜索页面的网址


        把网址粘过来,传入requests,写好正则表达式

url = 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1530020186092_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E5%B0%8F%E9%BB%84%E4%BA%BA'

html = requests.get(url).text
pic_url = re.findall('"objURL":"(.*?)",',html,re.S)

        另外,还要写一个循环,加载多张图片,这里由于有些图片可能存在网址打不开的情况,加个5秒超时控制。

pic_url = re.findall('"objURL":"(.*?)",',html,re.S)
i = 0
for each in pic_url:
    print each
    try:
        pic= requests.get(each, timeout=5)
    except requests.exceptions.ConnectionError:
        print '【错误】当前图片无法下载'
        continue

        再就是把网址保存下来,我们在事先在当前目录建立一个pictures目录,把图片都放进去,命名的时候,用数字命名

string = 'pictures\\'+str(i) + '.jpg'
    fp = open(string,'wb')
    fp.write(pic.content)
    fp.close()
    i += 1

        全部代码如下:

#-*- coding:utf-8 -*-
import re
import requests

url = 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1530020186092_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E5%B0%8F%E9%BB%84%E4%BA%BA'

html = requests.get(url).text
pic_url = re.findall('"objURL":"(.*?)",',html,re.S)
i = 0
for each in pic_url:
    print each
    try:
        pic= requests.get(each, timeout=5)
    except requests.exceptions.ConnectionError:
        print '【错误】当前图片无法下载'
        continue
    string = 'pictures\\'+str(i) + '.jpg'
    fp = open(string,'wb')
    fp.write(pic.content)
    fp.close()
    i += 1

        但是这样只能下载一个网址的图片,能不能加一个关键字搜索呢?

        又回来看网页,发现只要修改网址后面的关键字就能搜索不同的图片,只要在代码改url就能实现关键字搜索图片功能了


word = raw_input("Input key word: ")
    url = 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1530013590757_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=' + word 
    result = requests.get(url)

        最终代码:

# -*- coding:utf-8 -*-
import re
import requests


def dowmloadPic(html, keyword):
    pic_url = re.findall('"objURL":"(.*?)",', html, re.S)
    i = 0
    t = 0
    print('找到关键词:' + keyword + '的图片,现在开始下载图片...')
    for each in pic_url:
        print('正在下载第' + str(t + 1) + '张图片,图片地址:' + str(each))
        t += 1
        try:
            pic = requests.get(each, timeout=5)
        except requests.exceptions.ConnectionError:
            print('【错误】当前图片无法下载')
            continue
        string = 'pictures\\' + keyword + '_' + str(i) + '.jpg'
        # resolve the problem of encode, make sure that chinese name could be store
        fp = open(string, 'wb')
        fp.write(pic.content)
        fp.close()
        i += 1


if __name__ == '__main__':
    word = input("请输入关键词: ")
    url = 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1530013590757_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=' + word
    result = requests.get(url)
    dowmloadPic(result.text, word)

         运行结果:



         然而,运行之后发现只能下载30张图片,为什么呢?疑问原来是ajax异步请求加载图片,百度图片一开始只加载30张图片,当我们往下滑动滚动条时,页面会动态加载1条json数据,每条json数据里面包含了30条信息,信息里面又包含了图片的URL,JavaScript会将这些url解析并显示出来。这样,每次滚动到底就又多出30张图片。

        通过网上查询资料和请教同学,我又对之前的代码做了一些修改

再次分析网页:

        再次进入小黄人搜索页面,打开开发者工具,点击Network--XHR--acjson?tn...(下拉网页可看到)--Headers


        可以看到Query String Parameters里面的数据变化情况:

        word:我们搜索的关键字

        pn:当前加载的图片数量,每次增加30

        rn:每页有30张图片

        gsm:pn值的十六进制数,每次也是增加十进制的30


        找到规律,那就好办了,继续写代码...

编写代码:

        最终代码如下:

import requests
import os

def getManyPages(keyword,pages):
    params=[]
    for i in range(30,30*pages+30,30):
        params.append({
                      'tn': 'resultjson_com',
                      'ipn': 'rj',
                      'ct': 201326592,
                      'is': '',
                      'fp': 'result',
                      'queryWord': keyword,
                      'cl': 2,
                      'lm': -1,
                      'ie': 'utf-8',
                      'oe': 'utf-8',
                      'adpicid': '',
                      'st': -1,
                      'z': '',
                      'ic': 0,
                      'word': keyword,
                      's': '',
                      'se': '',
                      'tab': '',
                      'width': '',
                      'height': '',
                      'face': 0,
                      'istype': 2,
                      'qc': '',
                      'nc': 1,
                      'fr': '',
                      'pn': i,
                      'rn': 30,
                      'gsm': '1e',
                      '1488942260214': ''
                  })
    url = 'https://image.baidu.com/search/acjson'
    urls = []
    for i in params:
        urls.append(requests.get(url,params=i).json().get('data'))

    return urls


def getImg(dataList, localPath):

    if not os.path.exists(localPath):  # 如果给定的路径不存在文件夹,新建文件夹
        os.mkdir(localPath)

    x = 0
    for list in dataList:
        for i in list:
            if i.get('thumbURL') != None:
                print('正在下载:%s' % i.get('thumbURL'))
                ir = requests.get(i.get('thumbURL'))
                open(localPath + '%d.jpg' % x, 'wb').write(ir.content)
                x += 1
            else:
                print('图片链接不存在')

if __name__ == '__main__':
    word = input("请输入关键词: ")
    j = input("请输入页数: ")
    dataList = getManyPages(word,(int (j)))  # 参数1:关键字,参数2:要下载的页数
    getImg(dataList,'e:/Python/test1/pictures2/') # 参数2:指定保存的路径

        运行结果:



总结:

        终于完成第一个爬虫实践,过程不是很顺利,遇到不少问题,不过人生的快乐不就是在解决问题中寻找吗?做的项目也不是很难,结果可能还不够完美,但是这些都不是最重要的,最重要的,是过程中自己收获的经验和能力,这才是最宝贵的财富。也希望能和同学们一起探讨学习,共同进步。得意

        附一张爬虫流程图:




  • 14
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值