python动态爬取知乎_python爬虫从小白到高手 Day2 动态页面的爬取

今天我们说说动态页面的抓取,动态页面的概念不是说网页上的内容是活动的,而是刷新的内容由Ajax加载,页面的URL没有变化,具体概念问度娘。

就以男人都喜欢的美女街拍为例,对象为今日头条。

chrome打开今日头条 ->搜索

开发者工具->network选项卡

图2-1

很多条目,各种请求,但Ajax其实有其特殊的请求类型,它叫作xhr。在图6-3中,我们可以发现一个名称以getIndex开头的请求,其Type为xhr,这就是一个Ajax请求。用鼠标点击这个请求,可以查看这个请求的详细信息。

图2-2

选中这个xhr请求后,我们可以看到Request Headers中X-Requested-With:XMLHttpRequest,这就标记了此请求是Ajax请求。

点击一下Preview,即可看到响应的内容,它是JSON格式的。这里Chrome为我们自动做了解析,点击箭头即可展开和收起相应内容,初步分析这里返回的是页面上显示出来的前二十条信息。

图2-3

切换回第一个请求,我们发现Response中的信息是这样的

图2-4

这就是原始链接 https://www.toutiao.com/search/?keyword=街拍 所返回的内容,只有六十多行代码,执行了一些JavaScript,所以我们最终看到的页面不是由初始页面返回的,而是后来执行的JavaScript向服务器发送了Ajax请求,收到返回的真实数据后才显示出来的。这就是动态页面渲染的流程。

明白了整个流程后,我们要做的最重要的事就是分析返回数据的内容,用python模拟Ajax请求,拿到我们所希望抓取的数据。

def get_page(offset):

params = {

'offset': offset,

'format': 'json',

'keyword': '街拍',

'autoload': 'true',

'count': '20',

'cur_tab': '1',

'from': 'search_tab',

}

url = 'https://www.toutiao.com/search_content/?'

try:

response = requests.get(url, params=params)

if response.status_code == 200:

return response.json()

except requests.ConnectionError:

return None

下滑几次后,发现只有offset参数变化,所以,构造url,requests获得数据

这里拿到的数据是json格式的

def download_image(jsonData):

if jsonData.get('data'):

for item in jsonData.get('data'):

if item and 'article_url' in item.keys():

title = item.get('title')

article_url = item.get('article_url')

result = get_real_image_path(article_url)

if result: save_to_mongo(result)

'''

另外一种数据格式cell,cell type太多,主要分析上面一种

else:

#original_page_url

data = item.get('display')

#print(display)

#data = json.loads(display)

#print(data)

if data and 'results' in data.keys():

results = data.get('results')

original_page_urls = [item.get('original_page_url') for item in results]

# .get('results').get('original_page_url')

#title = item.get('display').get('title')

#print(title)

#print(original_page_urls)'''

取出数据中的data段,发现只有前四张图片的地址可以取到,剩下的图片必须进入文章页才能获得,我们取出文章页的url,requests获得文章页数据

def get_real_image_path(article_url):

headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}

response = requests.get(article_url, headers=headers)

soup = BeautifulSoup(response.text, "lxml")

title = soup.select('title')[0].get_text()

image_pattern = re.compile('gallery: JSON.parse\("(.*?)"\),', re.S)

result = re.search(image_pattern, response.text)

if result:

result = result.group(1).replace('\\', '')

data = json.loads(result)

if data and 'sub_images' in data.keys():

sub_images = data.get('sub_images')

images_urls = [item.get('url') for item in sub_images]

for image_url in images_urls: download_real_image(image_url)

return {

'title': title,

'url' : article_url,

'image_urls': images_urls

}

这里需要加入UA头,否则返回不了数据,拿到数据后,发现图片地址位于

图2-5

这里用正则表达式

gallery: JSON.parse\("(.*?)"\),

匹配符合条件的,gallery: JSON.parse("")中的数据\(\)这里在正则中表达的是转义字符,有兴趣的可以学习一下正则表达式,这里就不赘述了

我们从sub_images中拿到了所有图片地址,下载过程就很简单了

requests图片地址,获得的response中的content就是图片的数据

def download_real_image(url):

print('downloading---', url)

try:

response = requests.get(url)

if response.status_code == 200:

save_image(response.content)

return None

except RequestException:

print('request image fail---', url)

return None

def save_image(content):

files_path = '{0}/{1}'.format(os.getcwd(), 'tupian')

if not os.path.exists(files_path):

os.mkdir(files_path)

file_path = '{0}/{1}.{2}'.format(files_path, md5(content).hexdigest(), 'jpg')

if not os.path.exists(file_path):

with open(file_path, 'wb') as f:

f.write(content)

我们还可以把图片的标题和地址写入数据库

def save_to_mongo(result):

if db[MONGO_TABLE].insert(result):

print('save success', result)

return True

return False

完整代码:jjrt.py

import requests

import re

import json

from hashlib import md5

import os

from bs4 import BeautifulSoup

import pymongo

from config import *

import time

client = pymongo.MongoClient(MONGO_URL, connect=False)

db = client[MONGO_DB]

def get_page(offset):

params = {

'offset': offset,

'format': 'json',

'keyword': '街拍',

'autoload': 'true',

'count': '20',

'cur_tab': '1',

'from': 'search_tab',

}

url = 'https://www.toutiao.com/search_content/?'

try:

response = requests.get(url, params=params)

if response.status_code == 200:

return response.json()

except requests.ConnectionError:

return None

def save_to_mongo(result):

if db[MONGO_TABLE].insert(result):

print('save success', result)

return True

return False

def download_real_image(url):

print('downloading---', url)

try:

response = requests.get(url)

if response.status_code == 200:

save_image(response.content)

return None

except RequestException:

print('request image fail---', url)

return None

def save_image(content):

files_path = '{0}/{1}'.format(os.getcwd(), 'tupian')

if not os.path.exists(files_path):

os.mkdir(files_path)

file_path = '{0}/{1}.{2}'.format(files_path, md5(content).hexdigest(), 'jpg')

if not os.path.exists(file_path):

with open(file_path, 'wb') as f:

f.write(content)

def get_real_image_path(article_url):

headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}

response = requests.get(article_url, headers=headers)

soup = BeautifulSoup(response.text, "lxml")

title = soup.select('title')[0].get_text()

image_pattern = re.compile('gallery: JSON.parse\("(.*?)"\),', re.S)

result = re.search(image_pattern, response.text)

if result:

result = result.group(1).replace('\\', '')

data = json.loads(result)

if data and 'sub_images' in data.keys():

sub_images = data.get('sub_images')

images_urls = [item.get('url') for item in sub_images]

for image_url in images_urls: download_real_image(image_url)

return {

'title': title,

'url' : article_url,

'image_urls': images_urls

}

def download_image(jsonData):

if jsonData.get('data'):

for item in jsonData.get('data'):

if item and 'article_url' in item.keys():

title = item.get('title')

article_url = item.get('article_url')

result = get_real_image_path(article_url)

if result: save_to_mongo(result)

'''

另外一种数据格式cell,cell type太多,主要分析上面一种

else:

#original_page_url

data = item.get('display')

#print(display)

#data = json.loads(display)

#print(data)

if data and 'results' in data.keys():

results = data.get('results')

original_page_urls = [item.get('original_page_url') for item in results]

# .get('results').get('original_page_url')

#title = item.get('display').get('title')

#print(title)

#print(original_page_urls)'''

def main():

STARTPAGE = 1

ENDPAGE = 2

for i in range(STARTPAGE, ENDPAGE):

time.sleep(1)

offset = i * 20

jsonData = get_page(offset)

download_image(jsonData)

if __name__ == "__main__":

main()

config.py

MONGO_URL = 'localhost'

MONGO_DB = 'jiepai'

MONGO_TABLE = 'jiepai'

GROUP_START = 0

GROUP_END = 20

KEYWORD = '街拍'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567571.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python操作文件,报FileNotFoundError: [Error 2] No such file or directory错误

python操作文件时,报No such file or directory错误。 多次检查目录、文件名、语法都是对的。 折腾一番后,打开文件所在文件夹,并显示所有文件后缀名,才发现此文件并没有txt后缀名 解决方法: 添加文件的.txt后缀名&a…

python多标签分类_如何通过sklearn实现多标签分类?

sklearn支持多类别(Multiclass)分类和多标签(Multilabel)分类:多类别分类:超过两个类别的分类任务。多类别分类假设每个样本属于且仅属于一个标签,类如一个水果可以是苹果或者是桔子但是不能同时属于两者。多标签分类:给每个样本分…

练习ddt-file_data时,报错UnboundLocalError local variable ‘value‘ referenced before assignment

错误原因就是,在xx.yml中的内容无效 更改之前: 更改之后: 注意冒号后面要有空格 改完之后运行就能正确读取到了

python筛选数据求均值_Python Pandas实现数据分组求平均值并填充nan的示例

Python实现按某一列关键字分组,并计算各列的平均值,并用该值填充该分类该列的nan值。DataFrame数据格式fillna方式实现groupby方式实现DataFrame数据格式以下是数据存储形式:fillna方式实现1、按照industryName1列,筛选出业绩2、筛…

HTMLTestRunner.py内容

HTMLTesstRunner.py 修改后内容如下: """ A TestRunner for use with the Python unit testing framework. It generates a HTML report to show the result at a glance.The simplest way to use this is to invoke its main method. E.g.import u…

卷积神经网络原理_人脸识别背后,卷积神经网络的数学原理原来是这样的

在自动驾驶、医疗以及零售这些领域,计算机视觉让我们完成了一些直到最近都被认为是不可能的事情。卷积神经网络可能是这一巨大成功背后的关键组成模块。这次,我们将要使用卷积神经网络的思想来拓宽我们对神经网络工作原理的理解。简介过去我们接触到了密…

unittest读取ddt之-元组,嵌套元组,字典

注: (1)ddt数据驱动中,测试用例的执行次数是由data()传参的个数决定。传几个参数,就是执行几次测试用例。 (2)如果传的是多个元组(列表),那么可…

负载均衡策略_常见的负载均衡策略

轮询(Round Robin): 这种方法就会将收到的请求循环分配到服务器集群中的每台机器,即有效服务器。如果使用这种方式,所有的标记进入虚拟服务的服务器应该有相近的资源容量以及敷在相同的应用程序。如果所有的服务有相同或者相近的性能那么选择…

unittest-读取yaml文件

注: (1)yaml文件详解 yaml是一种数据格式,类似txt,excel,json 它只有两种数据类型: map对象(键值对,冒号后需要有空格) list列表对象,以-开头 读取之后是一个不定长…

白盒测试-修正条件判定覆盖

当程序中的判定语句包含多个条件时,运用多条件覆盖方法进行测试,其条件取值组合数目是非常大的。 修正条件判定覆盖要求在一个程序中每一种输入输出至少得出现一次,在程序中的每一个条件必须产生所有可能的输出结果至少一次,并且…

springboot整合shiro_Springboot整合Shiro:简洁的身份认证

简单的web应用进行身份认证的流程:1.对未认证的用户请求进行拦截,跳转到认证页面。2.用户通过用户名密码及其他凭证进行身份认证,认证成功跳转成功页面,认证失败提示相关失败信息。根据流程,采用shiro进行快速开发。1.…

python回车键绑定按钮_python tkinter 绑定回车键

# _*_ coding:utf-8_*_from Tkinter import *def submit(ev None):p.set(u.get())root Tk()root.title("测试")frame Frame(root)frame.pack(padx8, pady8, ipadx4)lab1 Label(frame, text"获取:")lab1.grid(row0, column0, padx5, pady5, stickyW)#绑…

2024年【安全生产监管人员】考试及安全生产监管人员模拟考试题库

题库来源:安全生产模拟考试一点通公众号小程序 2024年【安全生产监管人员】考试及安全生产监管人员模拟考试题库,包含安全生产监管人员考试答案和解析及安全生产监管人员模拟考试题库练习。安全生产模拟考试一点通结合国家安全生产监管人员考试最新大纲…

PICT工具安装使用

1、安装PICT 通过下载安装包pict33.msi, 链接:https://pan.baidu.com/s/1YWIA5XLNI0MMFkiQ-EqZ9w 提取码:ho7g 解压安装,安装成功后验证:打开cmd命令终端,输入pict显示如下即证明安装成功。 2、新建Mod…

茜在人名可以读xi吗_甘肃中专学校:初中毕业可以读大专吗?

初中毕业到兰州中专学校可以读大专吗?许多学生因为成绩的关系可能没能上普通高中,但是他们现在还不具备任何的专业知识和能力进入社会。很多孩子都想通过读大专具备进入社会的能力,那么初中毕业的学生是否能够读大专呢?成人高考初中毕业之后是可以读大…

测试用例设计思路

测试用例编写思路: 首先是明确测试范围: 接口测试 功能测试 界面测试(界面友好性、易用性、一致性) 兼容性测试(不同类型、型号手机、系统(手机系统、桌面系统)、分辨率、浏览器及其版本&a…

sql backup database备份d盘_SQL数据库备份概述

数据库备份方式概述为了防止意外删除,自然灾害等造成的损失,数据库备份是必须要的。数据库备份还可以用于mirror,replication等过程。了解数据库备份的原理对于处理数据库备份尤为重要。以下关于备份的概述只是前段时间兴起而写,由…

导入与上传

数据导入(Excel): 1、 下载模板(.xls)文件:将事先准备好的模板导入 2、 用户根据模板填写数据; 3、 用户上传数据->导入。 图片上传:图片(文件)上传:一般不会把图片…

python数字位数重排_Python面试题:给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数...

题目&#xff1a;方法&#xff1a;class Solution:def cmp(self,x,y):return (x > y) - (x < y)def comper(self,x,nums):temp 0for n in nums:n str(n)temp self.cmp(int(xn),int(nx))#print(self.cmp(int(x),n))return tempdef largestNumber(self, nums):"&qu…

选择嵌套_如何优雅地在JavaScript中访问嵌套对象

在JavaScript中访问嵌套对象以超酷的方式安全地访问JavaScript中的嵌套对象JavaScript是惊人的&#xff0c;我们都知道。但是JavaScript中的一些东西真的很奇怪&#xff0c;它们让我们大开眼界。其中一个问题是当您尝试访问嵌套对象时与此错误的对抗&#xff0c;无法读取未定义…