今日头条街拍图片爬取

配置文件

MONGO_URL='localhost' #链接地址
MONGO_DB='toutiao'   #数据库名称
MONGO_TABLE='toutiao' #表名

group_start=1 #起始点
group_end=200  #终点
keyword='街拍'

主程序

# -*- coding: utf-8 -*
import requests
import json
import re
from urllib.parse import urlencode #urlencode模块导入
from requests.exceptions import RequestException  #异常代码模块
from bs4 import BeautifulSoup
from config import * #注意要把config.py文件放在环境变量的目录下
import pymongo
import os
from hashlib import md5 #md5值的判断模块
from multiprocessing import Pool #多进程模块
#from json.decoder import JOSNDecodeError
from simplejson.scanner import JSONDecodeError

client=pymongo.MongoClient(MONGO_URL,connect=False) #声明MongoDB对象
db=client[MONGO_DB] #定义db





def get_page_index(offset,keyword): #抓取索引页内容
    data={
        'offset': offset, #offset是可变的
        'format': 'json',
        'keyword': keyword,#keyword是可以定义的
        'autoload':'true',
        'count': '20',                                         
        'cur_tab': 1,
        'from':'search_tab'
    }
#data是从XHR项目返回结果的Headers>Query String Parameters里的数据,Query String Parameters指的就是通过在URL中携带的方式提交的参数,也就是PHP中$_GET里的参数
    url='https://www.toutiao.com/search_content/?'+urlencode(data) #urlencode可以把字典对象变成url的请求参数
    try:
        response=requests.get(url)  #请求url
        if response.status_code==200:
            return response.text
        return None
    except RequestException: #所有requests的异常
        print('请求索引页出错')
        return None

def parse_page_index(html):#解析索引页
    try:
        data=json.loads(html) #对字符串进行解析,把字符串转化成json对象
        if data and 'data' in data.keys(): #判断json数据里面有data
            for item in data.get('data'): #
                yield item.get('article_url')  #构造一个生成器,把所有的article_url解析出来
    except JOSNDecodeError:  #判断网页为空的时候
        pass




def get_page_detati(url):#抓取详情页内容
    headers= {
   
   'accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
              'accept-encoding':'gzip, deflate, br',
              'accept-language':'zh-CN,zh;q=0.9',
              'cache-control':'max-age=0',
              'referer':'https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D',
              'upgrade-insecure-requests':'1',
              'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5083.400 QQBrowser/10.0.988.400'
              }
    try:
        response=requests.get(url,headers=headers)
        if response.status_code==200:
            return response.text
        return None
    except RequestException:
        print('请求详情页出错',url)
        return None

def parse_page_detail(html,url): #解析子页面
    try:
        soup=BeautifulSoup(html,'lxml') #用BeautifulSoup来解析获取的子页面html代码
        #print(soup)
        titie=soup.select('title')[0].get_text() #CSS选择器,选标签里面的文本信息
        print(titie)
        images_pattern=re.compile('gallery: (.*?),\n',re.S)  #用正则来匹配出gallery里面的数据
        result=re.search(images_pattern,html) #传入正则表达式对象
        data1 = result.group(1)
        data2=data1[12:-2] #去除没用的字符串
        data2=eval("'{}'".format(data2)) #去除双斜杠
        data = json.loads(data2)
        if data and 'sub_images' in data.keys(): #判断里面是否含有我们想要的数据
                sub_images=data.get('sub_images')
                images=[item.get('url') for item in sub_images]#列表的创建,每一个sub_images里面的每一个item里面的子元素
                for image in images:download_imagg(image) #循环下载所有的图片
                return {
                    'title':titie,
                    'url':url,
                    'images':images
                }
    except AttributeError:  #判断josn空的时候
        pass


def save_to_mongo(result):   #把字典传入mongodb
    if db[MONGO_TABLE].insert(result): #如果插入数据成功
        print('存储成功到MongoDB',result)
        return True
    return False

def download_imagg(url): #图片下载
    print('正在下载',url)
    try:
        response=requests.get(url)
        if response.status_code==200:
            #return response.text
            save_image(response.content) #content 返回二进制内容 ,图片一般都是返回content
        return None
    except RequestException:
        print('请求图片出错',url)
        return None

def save_image(content):
    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 = get_page_index(offset,keyword)
    #print(html)
    for url in parse_page_index(html):#利用for循环,提取出所有的article_url得到详情页网址
        html=get_page_detati(url)     #将提取到的url 传#解析索引页
        #print(url)
        #print(html)
        if html:
            #parse_page_detail(html)
            result=parse_page_detail(html,url)
            #save_to_mongo(result)
            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)#开启多进程

猜你喜欢

转载自blog.csdn.net/qq_15907907/article/details/80278502