抓取今日头条街拍美图

视频地址:
https://edu.hellobi.com/course/156/lessons

还有点小问题,不能正确执行,待解决。

import requests
from json.decoder import JSONDecodeError
import os
import json
import re
from bs4 import BeautifulSoup
#import pymongo
from requests.exceptions import RequestException
from urllib.parse import urlencode
#from config import *
#from hashlib import md5
#from multiprocessing import Pool

"""
client = pymongo.MongoClient(MONGO_URL,connect=False)
db = client[MONGO_DB]
"""

def get_page_index(offset, keyword):
    data = {
        'offset': offset,
        'format': 'json',
        'keyword': keyword,
        'autoload': 'true',
        'count': '20',
        'cur_tab': 3
    }

    url = 'http://www.toutiao.com/search_content/?' + urlencode(data)
    print(url)
    '''
    结果是
    url = http://www.toutiao.com/search_content/?offset=0&format=json&keyword=%E8%A1%97%E6%8B%8D&autoload=true&count=20&cur_tab=3
    但是通过这个url只得到了一个json格式的对象,不能得到我们想要的街拍的那个网址(http://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D),
    通过街拍这个网址得到的又是‘综合’,并不是我们想要的‘图集’
    故不能用soup =BeautifulSoup(url.text,'html.parser'),用soup.select('J_title')的方法来得到各个图集的链接地址
    '''
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text        #返回结果是一个字符串
        return None
    except RequestException:
        print('请求索引页出错!')
        return None

def parse_page_index(html):  # 由json对象data得到各图集的地址,并不是由列表页得到各图集的地址,因为没有访问列表页
    try:
        data = json.loads(html)                 # html是一个字符串,data是一个json的对象
        if data and 'data' in data.keys():     # 如果data不为空并且有key:data
            for item in data.get('data'):        # json对象获取字典中键对应值的方法是get,如果是字典,可以直接用dict['key']
                yield item.get('article_url')     # 得到各图集第一副图的地址
    except JSONDecodeError:                  # json对象为空可能引起的一些错误或者警告
        pass

def get_page_detail(url): #访问每个图集的第一副图的地址
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print('请求索引页出错!')
        return None

def save_image(content,title,num):  # 参数是二进制的图片
    '''
    file_path = '{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg')#每张图片得到一个md5的摘要值,如果图片一样,md5值也会一样
    '''
    file_path = '{0}/{1}.{2}'.format(os.getcwd(),title + '-'+str(num),'jpg')
    if not os.path.exists(file_path):
        with open(file_path,'wb') as f:
            f.write(content)
            f.close()

def download_image(url,title,num):                   #别忘了这个url的内容只有一张图片哦
    print('正在下载',url)
    try:
        response = requests.get(url)
        if response.status_code == 200:
            save_image(response.content,title,num)      #response.text是返回网页的正常显示内容,content是返回二进制内容,一般网页的返回用text,图片的返回用content
        return None
    except RequestException:
        print('请求图片页出错!')
        return None

def parse_page_detail(html, url):#在每个图集的第一副图的地址,即这个页面中找到图集的标题,以及图集所有图片的url
                                 #通过这个url可以真正的访问到第一副图,就可以用beautifulsoup了
    soup = BeautifulSoup(html, 'lxml')                         #用lxml来解析
    title = soup.select('title')[0].get_text()                 #得到网页标签页的标题,一般被title标签包裹(注意不是网页正文内的大标题,
                                                               #正文内的大标题一般被h1或者h2类似的标签包裹),最后如果是.text也可以,
                                                               #一种用属性,一种用方法
    print(title)
    '''
    import requests
    res =requests.get('http://www.toutiao.com/a6402374724713808129/#p=1')
    soup = BeautifulSoup(res.text, 'lxml')
    title = soup.select('title')[0].text                        #这样可以得到标签页title
    title_pattern = re.compile('<title>(.*?)</title>')
    title_result = re.search(title_pattern,res.text)            #可以直接写title_result = re.search('<title>(.*?)</title>',res.text)
    title_result.group(1)                                        #这样也可以得到标签页title
    '''
    images_pattern = re.compile('var gallery = (.*?);', re.S)  # 建立要寻找的字符串的正则表达式模型
    result = re.search(images_pattern, html)                   # 寻找所有符合模型的字符串
    if result:                                                 # 如果result不为空
        data = json.loads(result.group(1))                     # result.group(1)也是一个json对象,包含图片集中每张图片的地址,但是仔细观察会发现,地址有很多重复的,这是怎么回事呢,真的是重复的么?
        if data and 'sub_images' in data.keys():               #字典中得到键的列表集合也是dict1.keys()
            sub_images = data.get('sub_images')                #通过观察结果发现sub_images是一个列表,内容都是字典,有几张图片就有几个字典,字典的第一个键是url
            images = [item.get('url') for item in sub_images]  #images也是一个列表,有几张图片就有几个元素,元素都是url,注意这个url里面的内容只有一张图片
            num = 0
            for image in images:
                num += 1
                download_image(image,title,num)
            return {
                'title': title,   #标签页标题
                'url': url,       #第一副图的地址
                'images': images  #这个图集的地址列表
            }
        
def save_to_mongo(result):
    if db[MONGO_TABLE].insert(result):
        print('存储到MongoDB成功',result)
        return True
    return False
    
def main(offset):
    html = get_page_index(offset, '街拍')  # 该访问得到一个包含有个图集地址的json对象(并不是图集列表页)(是图集,不是综合或者视频)的内容,
                                           # html是一个json对象(不是图集列表页)
    for url in parse_page_index(html):     # 由json对象data得到各图集第一副图的地址url
        html = get_page_detail(url)        # 获取各图集第一副图url的正文
    if html:                               # 如果html不为空
            result = parse_page_detail(html, url)
    '''
    if result:save_to_mongo(result)
    '''

if __name__ == '__main__':
    main(0)

猜你喜欢

转载自blog.csdn.net/yj13811596648/article/details/83044361