• 15-分析Ajax请求并抓取今日头条街拍美图


    流程框架:

    抓取索引页内容:利用requests请求目标站点,得到索引网页HTML代码,返回结果。

    抓取详情页内容:解析返回结果,得到详情页的链接,并进一步抓取详情页的信息。

    下载图片与保存数据库:将图片下载到本地,并把页面信息及图片URL保存至MongoDB。

    开启循环及多线程:对多页内容遍历,开启多线程提高抓取速度。

     jiepai_picture.py

    '''有些网页直接请求得到的HTML代码,并没有包括在浏览器中直接看到的内容,因为一些信息通过Ajax加载、通过JS渲染生成的,此时要分析网页请求。
    本次用到的工具:
    网络库:requests、解析库:beautifulsoup和正则表达式、存储数据库:mongoDB、pymongo库。
    目标站点分析:
    '''
    from urllib.parse import urlencode
    import requests
    from requests.exceptions import RequestException
    import json
    from bs4 import BeautifulSoup
    import re

    import pymongo
    import sys
    sys.path.append('D://ASoft/Python/PycharmProjects/pachong/15-分析Ajax请求并抓取今日头条街拍美图') #将自己写的config.py的路径加入到系统路径中以便导入。
    from config import *
    client = pymongo.MongoClient(MONGO_URL,connect=False) #生成一个Mongo客户端,多进程时候connect=False,每个进程启动时才连接
    db = client[MONGO_DB] #定义一个DB

    import os
    from hashlib import md5
    from multiprocessing import Pool #引入进程池开启多进程
    from json.decoder import JSONDecodeError

    '''抓取索引页内容'''
    def get_page_index(offset,keyword): #使offset和keyword变成可变参数传递进来
    #得到网页请求的参数,参数见图1,注意:抓取的是“图集”标题页的内容
    data = {
    'offset': offset,
    'format': 'json',
    'keyword': keyword,
    'autoload': 'true',
    'count': '20',
    'cur_tab': '3',
    'from': 'gallery' #此属性要加上,否则可能会不会返回标签“图集”的url
    # 'pd':''
    }
    #将字典对象转换为url的请求参数,是urlib库提供的一种编码方法
    url = 'https://www.toutiao.com/search_content/?' + urlencode(data) #链接见图2
    try:
    #利用requests请求这个url
    response = requests.get(url)
    if response.status_code == 200:
    return response.text
    else:
    return None
    except RequestException:
    print('请求索引页出错')
    return None

    '''解析索引页信息'''
    def parse_page_index(html):
    try:
    data = json.loads(html) #生成一个json对象。
    if data and 'data' in data.keys():
    for item in data.get('data'):
    yield item.get('article_url') #生成器
    except JSONDecodeError:
    pass

    '''得到详情页详细信息'''
    def get_page_detail(url):
    headers = {
    # 'User-Agent': 'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)' #这个user-agent可以,有的user-agent可能会导致爬取到的源码不全。
    # 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36'
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'
    }
    try:
    #利用requests请求这个url,注意此处直接传入url来请求网页内容由于反爬机制可能会得不到网页内容,所以要requests.get方法要加入headers参数。
    response = requests.get(url=url,headers=headers)
    if response.status_code == 200:
    return response.text
    else:
    return None
    except RequestException:
    print('请求详情页出错')
    return None

    '''解析详情页信息:根据想要得到的信息,在爬取到的网页源码中搜索想要的信息,找到信息的标签位置,然后利用选择器或正则表达式解析。'''
    def parse_page_detail(html,url):
    soup = BeautifulSoup(html,'lxml') #由于图片链接信息在原始的网页源代码中可以找到,见图3,所以用Beautiful库解析,以lxml方式解析html
    try:
    title = soup.select('title')[0].get_text() #得到图片的名称
    except IndexError:
    print('title获取失败',url)
    # images_pattern = re.compile('var gallery = (.*?);', re.S) # 利用正则表达式解析图片链接地址
    images_pattern = re.compile('JSON.parse("(.*?)"),', re.S)
    # print(html)
    result = re.search(images_pattern,html)
    if not result:
    images_pattern = re.compile('JSON.parse("(.*?)"),', re.S)
    result = re.search(images_pattern,html)
    if result:
    data = json.loads(result.group(1)) #得到包含url的字典
    if data and 'sub_images' in data.keys():
    sub_images = data.get('sub_images') #得到一个列表,分析得知,列表中包含很多个集合,每个集合中包含一个键为url值为图片链接的键值对。
    images = [item.get('url') for item in sub_images] #包含网页街拍中一个组图中每张图片的链接
    #下载图片
    for image in images:
    download_image(image)
    #返回图片包含图片名称和链接的字典
    return {
    'title':title,
    'url':url,
    'images':images
    }

    #定义一个存储到MONGODB的方法
    def save_to_mongo(result):
    if db[MONGO_TABLE].insert(result): #如果存储成功
    print('存储到MongoDB成功',result)
    return True
    return False

    #将图片存储下来
    def download_image(url):
    print('正在下载',url)
    try:
    response = requests.get(url)
    print('---------')
    if response.status_code == 200:
    save_image(response.content) #response.content:返回二进制。response.text:返回正常网页源码结果。
    return None
    except RequestException:
    print('请求图片出错',url)
    return None

    #存储为图片
    def save_image(content):
    #文件路径包括三部分:路径、文件名、后缀。os.getcwd():当前项目的路径。md5(content).hexdigest():防止文件重复,如果图片内容相同则文件名相同。
    file_path = '{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg')
    if not os.path.exists(file_path):
    with open(file_path,'wb') as f:
    f.write(content)
    f.close()

    def main(offset):
    #得到索引页信息
    html_index = get_page_index(offset,KEYWORD)
    for url in parse_page_index(html_index): #url是每个详情页的url
    # 得到详细页信息
    html_detail = get_page_detail(url)
    if html_detail:
    result = parse_page_detail(html_detail,url) #得到解析后的title,url,images_url
    if result:
    save_to_mongo(result) #将得到的信息存储到数据库

    if __name__ == '__main__':
    # main()
    #抓取其他索引页
    groups = [x * 20 for x in range(GROUP_START,GROUP_END + 1)]
    pool = Pool() #声明一个进程池
    pool.map(main,groups)


    config.py
    '''把得到的信息存储到MONGODB中。配置信息放到配置文件中。'''
    MONGO_URL = 'localhost'
    MONGO_DB = 'toutiao'
    MONGO_TABLE = 'toutiao'

    GROUP_START = 1
    GROUP_END = 20

    KEYWORD = '街拍'


    程序执行可能有一些问题,尚待更正。













  • 相关阅读:
    MySQL——UPDATE更新
    MySQL——WHERE字句
    MySQL——查询数据
    MySQL——删除数据表
    MySQL——插入数据
    MySQL——创建数据表
    MySQL——数据类型
    MySQL——选择数据库
    MySQL——删除数据库
    MySQL——创建数据库
  • 原文地址:https://www.cnblogs.com/wisir/p/10090575.html
Copyright © 2020-2023  润新知