分析ajax请求,抓取今日头条图集

使用Python抓取今日头条图集

这是在看了静觅大神的爬虫视频后自己的一次尝试。虽然最后回过头来分析,发现也不是一次很难的抓取,但对于刚入门的小白还是有点不太友好。由于视频上传的已经有一段时间了,今日头条里也发生了一些改变。因此与视频里的有一定的出入,所以也是想在这里记录下,帮助下刚刚入坑的小伙伴。

1.分析今日头条图集内容

首先我们打开今日头条的网址,并在搜索框输入:街拍路人。进入所在的网址后,这个就是我们本次要抓取的URL。点击F12,进入开发者调试工具,我们选中Network,在下方选择XHR,刷新网页。我们发现当鼠标在往下拖动的时候,这边的数据也会越来越多,这就是运用了Ajax动态加载。

2.分析要抓取的网址内容

我们选择Name属性的数据来观察,发现其中的URL中其中一个标签(offset)在发生改变,我们选择Preview选项,搜索发现,每一条图集里面的图片都存储在data数据之中article_url之中,因此我们只要将其中的url抓取下来,然后再对这个URL进行分析。需要注意的是我们观察到的是json格式的数据,在使用Python抓取下来之后数据为字符串格式,因此我们在提取其中的article_url时,需要将其再转换成json格式。有利于我们顺利抓取。

3.分析提取后的URL

这个也是我遇到的最大的一个问题,在这边琢磨了很久。因为今日头条可能为了防止我们随意抓取,更换了存储的地方,并且加了一定的措施来进行反爬。我们进入其中的一个图集URL,我在xhr和all都找了都没有找到所有图片的信息,后面再doc中发现,将其放在了一个变量之中,并且是一个json格式。将图片的信息存储到了gallery这个键之中,就是在这个地方遇到了一个坑,在将字符串数据转为json数据时,发现这个前面全部都多了一个"\",这样就会报错。并且一开始使用正则提取URL时,范围过大。导致问题一直解决不了。后面在百度查找之后说是json格式问题,然后一步步print()输出,终于找到了这两个错误原因。最终也是解决了。

4.将数据存储到mongodb,图片下载保存到本地

最后将数据存储到mongodb,将图片下载到本地。

5.代码如下

我们创建两个py文件

jrtt_spider.py
import json
import os
import re
from hashlib import md5
from urllib.parse import urlencode
import requests
from bs4 import BeautifulSoup
from requests import RequestException
from multiprocessing import Pool

import pymongo


from config import *

client = pymongo.MongoClient(MONGO_URL,connect=False)   # 连接mongodb数据库
db = client[MONGO_DB]

# 得到图集URL
def get_old_url(offest,keyword):
    # 传入data
    data = {
        'aid': '24',
        'app_name': 'web_search',
        'offset': offest,
        'format': 'json',
        'keyword': keyword,
        'autoload': 'true',
        'count': '20',
        'en_qc': '1',
        'cur_tab': '1',
        'from': 'search_tab',
        'pd': 'synthesis',
    }
    url = 'https://www.toutiao.com/api/search/content/?'+urlencode(data)   # 编码处理
    # 封装头,不然可能会抓取不到
    headers = {'user-agent': 自己网站',
               'cookie':'自己网站cookie'}
    try:
        response = requests.get(url,headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print("错误1")
        return None


def parse_html(html):
    data = json.loads(html)   # 转化成json格式   当前的为字符串
    if data and 'data' in data.keys():
        for item in data.get('data'):
            yield item.get('article_url')


def get_new_url(url):
    try:
        headers = {'user-agent': 自己网站',
               'cookie':'自己网站cookie'}
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print("错误2")


def parse_new_html(htmls,url):
    soup = BeautifulSoup(htmls,"lxml")  
    title = soup.select('title')[0].get_text()     # 使用beautifulsoup提取
    print(title)
    images_pattern = re.compile(r'gallery: JSON.parse\("(.*?)"\),', re.S)   # 正则提取
    result = re.search(images_pattern,htmls)
    if result:
        datas = result.group(1).replace("\\",'')       # 将\替换点
        data = json.loads(datas)
        if data and 'sub_images' in data.keys():
            sub_images = data.get('sub_images')
            images = [item.get('url') for item in sub_images]
            for image in images:
                downloads_images(image)         # 保存数据下载图片
            return {
                'title':title,
                'images':images,
                'url':url
            }

# 下载图片
def downloads_images(url):
    print("正在下载",url)
    try:
        headers = {'user-agent': 自己网站',
               'cookie':'自己网站cookie'}
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            save_images(response.content)
        return None
    except RequestException:
        print("错误2")
        return None


def save_images(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)


def save_mongodb(result):
    if db[MONGO_TABLE].insert(result):
        print("存储成功")
        return None
    return False


def main(offset):
    html = get_old_url(offset, Keyword)
    for url in parse_html(html):
        htmls = get_new_url(url)
        if htmls:
            result=parse_new_html(htmls, url)
            if result:
                save_mongodb(result)


if __name__ == '__main__':
    groups = [x*20 for x in range(GROUP_START,GROUP_END+1)]
    pool = Pool()
    pool.map(main,groups)

config.py

MONGO_URL = "localhost"
MONGO_DB = 'toutiao'
MONGO_TABLE = "toutiao"
GROUP_START = 0
GROUP_END = 20
Keyword = '街拍路人'

下面是我抓取到的数据,如果你是一个小白,希望对你有所帮助。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值