ajax动态抓取今日头条街拍美图

来源:互联网 发布:投资新三板风险知乎 编辑:程序博客网 时间:2024/05/29 11:59

1、分析网站源码。


网站是局部动态变化,offset变化加载内容,变化范围为0,20,40···

首先要获取索引页代码数据,定义索引页,由于是ajax请求,offset根据索引变化0、20、40···,用requests获取网页代码,urlcode将字典转换为url请求参数,然后异常处理,根据url_code状态码判断请求是否成功,返回文本格式,最后定义main函数调用。可根据可变参数’offset’和’keyworld’参数调用函数,改为def get_page-index(offset,keyworld)

fromurllib.parse importurlencode
import requests
from requests.exceptionsimport RequestException

def get_page_index():
   
data = {
       
'offset':0,
       
'format':'json',
       
'keyword':'街拍',
       
'autoload':'true',
       
'count':'20',
       
'cur_tab':3
   
}
    url
= 'https://www.toutiao.com/search_content/?'+urlencode(data)
   
try:
       
response =requests.get(url)
       
if response.status_code== 200:
           
return response.text
       
return None
    except
RequestException:
       
print("请求索引页错误")
       
return None

def
main():
   
html=get_page_index()
   
print(html)

if __name__== '__main__':
   
main()

2、解析索引页,因为html返回的是json格式的字符串对象,json.loads加载json格式文件。判断data[‘data’]键是否存在,若存在,返回’article_url’的值

def parse_page_index(html):    data = json.loads(html)    if data and 'data' in data.keys():        for item in data.get('data'):            yield item.get('article_url')

然后在main函数中调用解析页的url

for url in parse_page_index(html):    print(url)

3、获取详情页代码

ef get_page_detail(url):    try:        response = requests.get(url)        if response.status_code == 200:            return response.text        return None    except RequestException:        print("请求详情页错误",url)        return None

4、解析详情页数据。

分析详情页源代码


查看详情页的网站源代码,发现图片集的url都在gallery键的值中。

首先,获取每个图片集的标题title,用select选择title标签下的文本

def parse_page_detail(html):    soup = BeautifulSoup(html,'lxml')    title = soup.select('title')[0].get_text()    print(title)

在main函数中判断html是否正确,返回结果

main():    html = get_page_index(0,'街拍')    for url in parse_page_index(html):        html = get_page_detail(url)        if html:            parse_page_detail(html)

获取每个图片集中的图片信息,所有图片信息都在gallery键的值中,通过re.comlile正则表达式解析,然后用search得到结果,因为此时得到的结果中信息不正确,有很多多余的反斜杠’\’,于是利用replace去掉斜杠。

获取到的结果为

image_pattern = re.compile('gallery: JSON.parse[(]"(.*?)"[)],\n',re.S)result = re.search(image_pattern,html)if result:    result = result.group(1).replace('\\','')    print(result)

结果是json字符串的格式,需要用loads解析,提取其中的每张照片的url,最后返回的是图集的标题、链接和每张图片的url

data=json.loads(result)if data and 'sub_images' in data.keys():    sub_images=data.get('sub_images')    images_url=[item['url'] for item in sub_images]    return {        'title':title,        'url':url,        'images_url':images_url    }

输出的结果为:


此时,所有的信息已经提取完毕,开始存储数据

5、把数据存储到mongodb数据库中,首先在同一目录下,建立配置文件config.py,

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

通过from config import *调用该文件

#声明mongodb数据库对象client=pymongo.MongoClient(MONGO_URL)db=client[MONGO_DB]

然后定义函数存储到数据库中,并判断如果存储成功输出相应信息

def save_to_mongo(result):    if db[MONGO_TABLE].insert(result):        print("存储到mongodb成功",result)        return True    return False

6、接下来是根据图片链接下载图片

首先定义一个函数,利用pathlib库根据传入的目录名创建一个文件目录

def create_dir(name):    #根据传入的目录名创建一个目录,这里用到了 python3.4 引入的 pathlib 。    directory = Path(name)    if not directory.exists():        directory.mkdir()    return directory

然后定义下载图片函数,要求返回的是content,是二进制文件

def download_image(save_dir,url):    print("正在下载:",url)    try:        response = requests.get(url)        if response.status_code == 200:            #调用存储图片函数,返回二进制            save_image(save_dir,response.content)        return None    except RequestException:        print("请求图片出错",url)        return None

定义存储图片函数

def save_image(save_dir,content):    '''把文件保存到本地,文件有三部分内容(路径)/(文件名).(后缀)    format构造字符串(项目路径,文件名,格式),md5文件名可以避免重复'''    #os.getcwd()程序同目录    #file_path='{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg')    file_path = '{0}/{1}.{2}'.format(save_dir, md5(content).hexdigest(), 'jpg')    #如果文件不存在,开始存入    if not os.path.exists(file_path):        with open(file_path,'wb') as f:            f.write(content)            f.close()

在parse_page_detail函数中,调用download_image

root_dir = create_dir('D:\spider\jiepai'# 保存图片的根目录download_dir = create_dir(root_dir / title)  # 根据每组图片的title标题名创建目录for image in images:    download_image(download_dir, image)    #下载所有的图片  

 

最后完成的效果图