requests爬取今日头条街拍的两种方法

 

分析网页

今日头条的网页是通过AJAX加载的所以如果单纯的复制网页是无法查看到内容的,只能看到一堆字典形式HTML代码。

这里发现URL的参数共有offset,format,keyword,autoload,count,cur_tab,from,这七种。

往下翻,在Query String Parameters中就能发现这些参数

requests爬取今日头条街拍的两种方法_第1张图片

往下翻,查看新的AJAX,点开NETWORK对比Query String Parameters,会发现只有offset发生了变化

requests爬取今日头条街拍的两种方法_第2张图片

再回过头观察Query String Parameters 和requests.URL。会发现从https://www.toutiao.com/search_content/?

后开始参数都是按顺序拼接的。

代码

import requests,json
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
def get_page():
    url = 'https://www.toutiao.com/search_content/?'
    params={
        'offset':' 0',
        'format': 'json',
        'keyword': '街拍',
        'autoload':'true',
        'count': '20',
        'cur_tab': '1',
        'from': 'search_tab',
    }
    #requests自带params参数能够补全URL可代替urllib.urlopen()的拼接
    response = requests.get(url,params=params)
    try:
        if response.status_code == 200:
            #如果状态码为200(即响应成功)则返回json格式的响应内容
            #在requests中自带json()方法
            return response.json()
        else:
            return None
    except RequestException as f:
        return f
def main():
    html = get_page()
    #输出响应内容
    print(html)
if __name__ == '__main__':
    main()

 

返回的结果如下

requests爬取今日头条街拍的两种方法_第3张图片

返回了一堆杂乱的json代码,但是chrome功能十分强大,自动帮整理。点开Preview,需要的东西全在data中

requests爬取今日头条街拍的两种方法_第4张图片

requests爬取今日头条街拍的两种方法_第5张图片

requests爬取今日头条街拍的两种方法_第6张图片

requests爬取今日头条街拍的两种方法_第7张图片

这次只取标题和图片链接,如果你愿意,还可以通过media_url爬取它所有文章的内容

先取标题,通过打印出的标题会发现有的标题为空。

def parse_page(html):
    data =html.get('data')
    for item in data:
        title = item.get('title')
        print(title)

 requests爬取今日头条街拍的两种方法_第8张图片

没有标题的话肯定就不存在有内容,所以需要做一个判断,标题是否为空。

def parse_page(html):
    data =html.get('data')
    for item in data:
        title = item.get('title')
        # print(title)   打印出标题
        if title is not None:
            for url in item.get('image_list'):
                #yield 返回,并生成一个生成器
                yield{
                    'title':title,
                    'url':url
                }

因为生成了一个生成器想要查看内容必须循环。

 

def main():
    html = get_page()
    #输出响应内容
    # print(html)
    page = parse_page(html)
    for i in page:
        print(i)

 查看我们打印的内容会发现url很奇怪,我们得到了一个字典形式的不完全的URL,通过dict.get()方法得到值并补全代码

  'url':'https:'+url.get('url')

再次打印,就出现了我们想要的结果

最后一步,下载图片

def save_image(img_list):                                                                             
    #首先判断是否存在该文件夹,如果没有title文件夹 ,则创建一个文件夹                                                              
    if not os.path.exists(img_list.get('title')):                                                     
        os.mkdir(img_list.get('title'))                                                               
    try:                                                                                              
        response = requests.get(img_list.get('url'))                                                  
        #通过hash的md5的算法,防止出现重复名                                                                        
        haxi = md5(response.content).hexdigest()                                                      
        file_path = '{0}/{1}.{2}'.format(img_list.get('title'), haxi, 'jpg')                          
        if response.status_code == 200:                                                               
            with open((file_path),'wb')as f:                                                          
                f.write(response.content)                                                             
                print('图片名:{0},图片链接:{1}'.format(img_list.get('title'),img_list.get('url')))           
        else:                                                                                         
            print('已经下载图片',file_path)                                                                 
    except :                                                                                          
        print('下载错误')                                                                                 

爬取多页

 这是只是爬取第一页,如果想要爬取更多,只需要将params的的offset作为一个参数,修改一下就可以了。

def main():                        
    for i in range(5):             
        offset = i *20             
        html = get_page(offset)    

完整代码 

import requests,json
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
import os
from hashlib import md5
def get_page(offset):
    url = 'https://www.toutiao.com/search_content/?'
    params={
        'offset':offset,
        'format': 'json',
        'keyword': '街拍',
        'autoload':'true',
        'count': '20',
        'cur_tab': '1',
        'from': 'search_tab',
    }
    #requests自带params参数能够补全URL可代替urllib.urlopen()的拼接
    response = requests.get(url,params=params)
    try:
        if response.status_code == 200:
            #如果状态码为200(即响应成功)则返回json格式的响应内容
            #在requests中自带json()方法
            return response.json()
        else:
            return None
    except RequestException as f:
        return f
#解析内容
def parse_page(html):
    data =html.get('data')
    for item in data:
        title = item.get('title')
        # print(title)   打印出标题
        if title is not None:
            for url in item.get('image_list'):
                #yield 返回,并生成一个生成器
                yield{
                    'title':title,
                    'url':'https:'+url.get('url')
                }
def save_image(img_list):
    #首先判断是否存在该文件夹,如果没有title文件夹 ,则创建一个文件夹
    if not os.path.exists(img_list.get('title')):
        os.mkdir(img_list.get('title'))
    try:
        response = requests.get(img_list.get('url'))
        #通过hash的md5的算法,防止出现重复名
        haxi = md5(response.content).hexdigest()
        file_path = '{0}/{1}.{2}'.format(img_list.get('title'), haxi, 'jpg')
        if response.status_code == 200:
            with open((file_path),'wb')as f:
                f.write(response.content)
                print('图片名:{0},图片链接:{1}'.format(img_list.get('title'),img_list.get('url')))
        else:                                  
            print('已经下载图片',file_path)
    except :
        print('下载错误')
def main():
    for i in range(5):
        offset = i *20
        html = get_page(offset)
    #输出响应内容
    # print(html)
    page = parse_page(html)
    for img_list in page:
        save_image(img_list)
if __name__ == '__main__':
    main()

方法二

这是第一次尝试抓取的时候,发现dict中并没有'data' 这个键。我查找了很久,终于发现有一个‘html'的键,所对应的值为整个HTML页面

requests爬取今日头条街拍的两种方法_第9张图片

因为只是测试,所以只爬取了一页,也没有做状态码的判断

完整代码 

import requests
from bs4 import BeautifulSoup
import  os
from hashlib import md5
def get_one_page(offset):
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36'
    }
    params={
        'offset': offset,
        ' format': 'json',
        'keyword': ' 街拍',
        'autoload': 'true',
        'count': '20',
        'cur_tab': '1',
    }
    url = 'https://www.toutiao.com/search_content/?'
    response = requests.get(url,headers=headers,params=params)
    if response.status_code==200:
        return response.json()
    return None
def parse_page(html):
    data = html.get('html')
    soup =BeautifulSoup(data,'lxml')
    body=soup.select('section')
    for i in body:
        title = i.select('.line3')[0].string
        if title is not None:
            images=i.select('.list_img_holder img')
            for image in images:
                yield {
                    'title':title,
                    'image':image['src']
                }
def save(page):
        if not os.path.exists(page.get('title')):
            os.mkdir(page.get('title'))
        try :
            response =requests.get(page.get('image'))
            i = md5(response.content).hexdigest()
            file_path = '{0}/{1}.{2}'.format(page.get('title'), i, 'jpg')
            if response.status_code==200:
                with open(file_path,'wb')as f:
                    f.write(response.content)
            else:
                print('Already Downloaded',file_path)
        except :
            print('file_path not save image')
def main():
    offset = 0
    html = get_one_page(offset)
    print(html)
    k=parse_page(html)
    for page in k:
        save(page)
if __name__ == '__main__':
    main()



 

你可能感兴趣的:(requests)