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

1、分析网站源码。

ajax动态抓取今日头条街拍美图_第1张图片

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

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

from urllib.parse import urlencode
import requests
from requests.exceptions import 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、解析详情页数据。

分析详情页源代码

ajax动态抓取今日头条街拍美图_第2张图片

查看详情页的网站源代码,发现图片集的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
    }

输出的结果为:

ajax动态抓取今日头条街拍美图_第3张图片

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

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)    #下载所有的图片  

 

最后完成的效果图

ajax动态抓取今日头条街拍美图_第4张图片

 ajax动态抓取今日头条街拍美图_第5张图片

你可能感兴趣的:(爬虫)