• 采集淘宝美人库


    爬虫一共就四个主要步骤:

    1、明确目标:明确需要抓取那些内容,在哪个网页
    2、爬:分析网站结构,将所有的网站的内容全部爬下来
    3、取:提取我们所需要的数据
    4、处理数据:按照需求存储使用

    第一步:

    明确目标:
    网站url: https://mm.taobao.com/search_tstar_model.htm?spm=5679.126488.640745.2.2dc084317xDoLY
    抓取内容:
    头像:存储在本地硬盘。
    名字,城市,身高,体重,点赞数: 保存在mysql数据库
    说明:这里只是用作教程并非真的要将爬取的内容作为其它用途

    第二步爬:

    使用到的模块:

    python 3.6: python环境
    requests: 发送请求
    pymysql: 操作mysql
    queue: 队列
    random: 产生随机数

    想要看懂这篇文章,还是需要那么一丢丢的python基础知识。

    分析网页结构:
    1、确定网页数据的请求方式'GET'还是'POST',ajax异步请求还是直接浏览器请求,一般ajax请求的url跟我们在浏览器上的url地址栏看到是不一样的,所以我们需要使用到浏览器的开发者工具抓包查看。

    我观察了下淘女郎这个模特库首页是有分页的,这里有个小技巧,来确定请求方式:
    我这里使用的是谷歌浏览器,按F12打开浏览器的开发者工具,切换到netrork选项,然后将网页拉到最下面有分页的地方。

    我们观察url地址栏上的地址并没有发生改变,所以地址栏上的url对我们没有帮助!这也说明这个网页的内容是通过ajax加载的。

    查看图片上4的位置所有请求的url,发现第一个请求并没有返回任何数据,只有第二个请求有返回数据第三个请求之后的全部都是请求图片的。

    选中第二个请求,选中response,查看返回的数据是json数据,可以将json数据复制到json在线解析网站解析看下返回的是什么,解析出来后我们发现,json数据 "searchDOList" 字段就是包含了当前页所有淘宝小姐姐的信息。

    确定我们需要的数据就是在第二请求之后,我们回到开发者管理工具,点击headers查看请求头信息。

    标红框的这几个数据等会写爬虫会用到,分析到这里我们就拿到了等下写爬虫需要的数据:

    ```

    url:https://mm.taobao.com/tstar/search/tstar_model.do?_input_charset=utf-8
    请求方式:post
    post参数:
        q:
        viewFlag:A
        sortType:default
        searchStyle:
        searchRegion:city:
        searchFansNum:
        currentPage:2
        pageSize:100
    
    ```


    测试获取页面内容:

    import requests
    
    url='https://mm.taobao.com/tstar/search/tstar_model.do?_input_charset=utf-8'
    headers={'user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36',
            'referer':'https://mm.taobao.com/search_tstar_model.htm?spm=5679.126488.640745.2.1b545b81UeJRlv'}
    data={'viewFlag':'A',
    'sortType':'default',
    'currentPage':2,
    'pageSize':100}
    res =requests.post(url=url,data=data,headers=headers).json()

     完整版代码:

      注:程序进行了优化,图片下载本地生成缩略图:

      在173行使用用了一个 break。值采集一个模特信息,需要采集所有,将这行屏蔽:

      1 '''
      2 程序说明:采集mm.taobao.com模特图片和详细内容。将采集的数据保存到sqlite数据库中
      3 保存图片已采集模特的userId为文件名
      4 '''
      5 import requests
      6 import os
      7 import uuid
      8 import re
      9 import sqlite3
     10 from time import sleep
     11 from PIL import Image#处理图片
     12 #当前项目路径
     13 BASE_PATH=os.getcwd()
     14 DB ='taobao_mm.db'#数据保存的数据库名
     15 TABLE ='mm_table'   #数据保存的表名
     16 #缩略图尺寸:
     17 IMG_W=600
     18 IMG_H=600
     19 #创建数据sqlite数据库和表
     20 def create_db_table():   
     21     create_table_sql='''
     22             create table IF NOT EXISTS %s(userid integer,
     23             realName varchar(50),
     24             city varchar(50),
     25             height varchar(10),
     26             weight varchar(10),
     27             totalFavorNum int(11),
     28             img varchar(225),
     29             content text
     30             )
     31         '''%(TABLE)
     32     #链接数据库
     33     db=sqlite3.connect(DB)
     34     #创建游标
     35     cur =db.cursor()
     36     #执行sql语句
     37     cur.execute(create_table_sql)
     38     #提交结果
     39     db.commit()
     40     #关闭数据库
     41     db.close()
     42 #插入数据   
     43 def insert_res(data):
     44     #确定数据库已经创建   
     45     create_db_table()
     46     
     47     sql='''insert into %s(userid,realName,city,height,weight,totalFavorNum,img,content) 
     48            values('%s','%s','%s','%s','%s','%s','%s','%s')
     49     '''%(TABLE,data.get('userid'),data.get('realName'),data.get('city'),data.get('height'),data.get('weight'),data.get('totalFavorNum'),data.get('img'),data.get('content'))
     50     #链接数据库
     51     db=sqlite3.connect(DB)
     52     #创建游标
     53     cur =db.cursor()
     54     #执行sql语句
     55     cur.execute(sql)
     56     #提交事务
     57     db.commit()
     58     #关闭数据库
     59     db.close()
     60     return True
     61 
     62 
     63 #处理图片的函数,2个参数:1)图片地址 2)模特id
     64 def upload_img(url,userId):
     65     #保存图片已采集模特的userId为文件名
     66     relative_addr='upload'+'/%d/'%(userId)
     67     #判断绝对地址文件夹是否存在:os.path.join(BASE_PATH,relative_addr)
     68     absolut_addr=os.path.join(BASE_PATH,relative_addr)
     69     #如果不存在。则创建文件夹
     70     if not os.path.exists(absolut_addr):
     71         os.makedirs(absolut_addr)#创建文件夹
     72     #取得当前图片的后缀
     73     postfix =url.split('.')[-1]#文件名已.号分割。
     74     #已当前userId为当前的图片名
     75     file_name=str(userId)+'.'+postfix
     76      #文件相对地址:
     77     file_url=relative_addr+file_name
     78     #请求url图片地址。
     79     img_source=requests.get('http:'+url)
     80     #将响应的结果保存到文件中file_url中:
     81     with open(file_url,'wb') as f:
     82         f.write(img_source.content)
     83     #生成缩略图
     84     img =Image.open(file_url)
     85     img.thumbnail((IMG_W,IMG_H))
     86     img.save(file_url,img.format)
     87     #返回相对地址:
     88     return file_url
     89 #爬取用户详细信息
     90 def get_content(userId):
     91     headers={'user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36',
     92         'referer':'https://mm.taobao.com/search_tstar_model.htm'}
     93     url='https://mm.taobao.com/self/aiShow.htm?userId='+str(userId)
     94     img_source=requests.get(url=url,headers=headers)
     95     html=img_source.text
     96     #正则匹配文章内容
     97     content =re.search('<div.*?id="J_ScaleImg">(.*?)</div>',html,re.S).group(1)
     98     #正则匹配文章中的所有图片
     99     img_list =re.findall('src="(.*?)"',content,re.S)
    100     #确定文件的保存路径
    101     relative_addr='upload'+'/%d/'%(userId)
    102     print(relative_addr)
    103     #判断绝对地址文件夹是否存在:os.path.join(BASE_PATH,upload_addr)
    104     absolut_addr=os.path.join(BASE_PATH,relative_addr)
    105     if not os.path.exists(absolut_addr):
    106         os.makedirs(absolut_addr)#创建文件夹
    107     #循环处理图片
    108     temp_num=0
    109     for url_img in img_list:        
    110         #取得原文件后缀
    111         postfix =url_img.split('.')[-1]#文件名已.号分割。
    112         #新文件文件名,格式为 : userID_数字.后缀
    113         file_name='%s_%s.%s'%(str(userId),str(temp_num),postfix)
    114         #temp_num累加1
    115         temp_num = temp_num+1
    116         #文件相对地址:
    117         file_url=relative_addr+file_name
    118         #请求url图片地址。
    119         img_source=requests.get('http:'+url_img)
    120         #将响应的结果保存到文件中:
    121         with open(file_url,'wb') as f:
    122             f.write(img_source.content)
    123         #生成缩略图
    124         try:
    125             img =Image.open(file_url)
    126             img.thumbnail((IMG_W,IMG_H))
    127             img.save(file_url,img.format)
    128         except Exception as e:
    129             print(file_name,'')
    130         else:
    131             continue
    132         #替换采集内容中的图片地址
    133         content =content.replace(url_img,'/'+file_url)
    134     return content
    135 #请求列表分页数据,url:采集地址,page:页数
    136 def main(url,page):    
    137     headers={'user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36',
    138             'referer':'https://mm.taobao.com/search_tstar_model.htm?spm=5679.126488.640745.2.1b545b81UeJRlv'}
    139     print('开始:')
    140     for i in range(1,page+1):        
    141         data={'viewFlag':'A',
    142         'sortType':'default',
    143         'currentPage':i,
    144         'pageSize':100}
    145         r =requests.post(url=url,data=data,headers=headers)
    146         #判断请求状态
    147         #根据请求状态进行处理,请求次数过多出错,就需要使用代理
    148         print('第一页状态:',r.status_code,end='')
    149         if r.status_code ==200:
    150             res =r.json() #res 保存请求响应的结果
    151             res_list=res['data']['searchDOList']  #保存响应的数据列表          
    152             #循环列表,将数据插入到数据库中 
    153             for item in res_list:
    154                 #判断图片文件夹是否存在:
    155                 relative_addr='upload'+'/%d/'%(item['userId'])#相对地址
    156                 #判断绝对地址文件夹是否存在:os.path.join(BASE_PATH,upload_addr)
    157                 absolut_addr=os.path.join(BASE_PATH,relative_addr)
    158                 if os.path.exists(absolut_addr):
    159                     #跳出本次循环,进行下次循环 
    160                     continue
    161                 insert_data={ 'realName':item['realName'],
    162                             'userid':item['userId'],
    163                             'city':item['city'],
    164                             'height':item['height'],
    165                             'weight':item['weight'],
    166                             'totalFavorNum':item['totalFavorNum'],
    167                             'img':upload_img(item['avatarUrl'],item['userId']),
    168                             'content':get_content(item['userId'])#详细内容图片过多。只做参考
    169                            }               
    170                 #将数据插入到数据库中
    171                 print('
    ',item['realName'],'-',item['userId'],':已采集','
    ',end='')                 
    172                 insert_res(insert_data)
    173                 break;#注意 ,需要采集所有需要将这句删除。
    174                 sleep(1)#每次插入操作间隔1秒,方式sqlite被锁
    175         else:
    176             print('请求是失败,页数:',i)
    177     print('结束!',)
    178 #print(res_list)
    179 #print(res)
    180 if __name__ =='__main__':
    181     url='https://mm.taobao.com/tstar/search/tstar_model.do?_input_charset=utf-8'
    182     main(url,1)#第一个参数为采集地址。参数2:采集页数
    View Code

    效果:

  • 相关阅读:
    Oracle中的rownum
    关于Oracle12c中无scott用户的问题
    docker 1.13 是什么版本?
    ImportError: cannot import name 'SQLALchemy'
    mac配置iterm2,iterm2使用方法
    docker 时区
    jupyter 500 : Internal Server Error
    sublime conda 切换环境
    mac frida安装(使用网易木木模拟器)
    \u开头两个字符的是什么编码?
  • 原文地址:https://www.cnblogs.com/wu-chao/p/8424582.html
Copyright © 2020-2023  润新知