简书爬ajax接口获取csrf,python3爬虫项目实战(二)ajax请求爬取网站图片

这次的项目是利用ajax来对网站图片进行爬取。Ajax的作用就是在保证页面不被刷新的情况下,与服务器交换数据从而只更新部分网页的技术。

这里不多讲述ajax技术,先给出网页,来具体分析。

https://www.toutiao.com/

这个是头条的网站,我们在搜索框输入“街拍”二字,点击搜索,就可以进入到搜索界面,按一下F12就可以进入检查模式,在这个模式下,我们点击Network选项卡,选择XHR后就可以看到下面请求(如果没有按Ctrl+R刷新即可),这里XHR是一种页数的Ajax的请求类型。我们点开第一个请求,可以看到很多的信息,比如Request URL等。这里我们只来分析这个URL。

edc730128eee

找到Ajax请求

Request URL: https://www.toutiao.com/api/search/content/?aid=24&app_name=web_search&offset=0&format=json&keyword=%E8%A1%97%E6%8B%8D&autoload=true&count=20&en_qc=1&cur_tab=1&from=search_tab&pd=synthesis&timestamp=1583219891329

可以看到请求的参数:aid,app_name,offset,format,keyword,autoload,count,en_qc,cur_tab,from,pd,timestamp。

在这里,我们通过构造这些参数,就可以访问到相同的内容。

部分参数含义

这里很多参数都是固定的,比如aid,app_name等,这里不进行分析,有兴趣的话可以百度查一查,但是有一些参数比较有意思,比如offset。

大家如果拖动页面,页面刷新的时候,会出现新的Ajax请求,这里对应的请求参数offset会发生变化:每刷新一页,offset加20,因此我们如果通过变化offset可以获取多页的图片,我们通过group = ([x*20 for x in range(GROUP_START, GROUP_STOP+1)])来构造多页的图片请求。

keyword参数就是我们输入的搜索关键词,进行编码后的结果。

还有一个参数是timestamp,就是时间戳的意思,这个参数测试的时候发现,可以省略,依然可以爬取到图片,但还是给出构造的方法:

timestamp = int(time.time())

下面给出构造参数的格式:

params = {

'aid':'24',

'app_name':'web_search',

'offset':offset,

'format':'json',

'keyword':'街拍',

'autoload':'true',

'count':'20',

'en_qc':'1',

'cur_tab':'1',

'form':'search_tab',

'pd':'synthesis',

#时间戳参数,缺失了也不影响

#'timestamp':timestamp

}

将这些参数和网页链接连接起来:

url = 'https://www.toutiao.com/api/search/content/?'+urlencode(params)

就可以对网站进行访问。具体的工程代码在下面。

在刚开始运行的时候会出现一些问题,如下图所示:

edc730128eee

文件夹名的报错

这个错误是因为我们是以标题名作为文件夹名,有时候标题名会有一些字符,使其无法成为文件夹的名字。

已经解决的命名问题有如下两个:

#OSError: [Errno 22] 文件名、目录名或卷标语法不正确。: 'jiepai/29张街拍,定格不一样的"空城"纸坊'`

#OSError: [Errno 22] 文件名、目录名或卷标语法不正确。: 'jiepai/街拍小技巧|让你的街拍照片秒变时尚大片!'

所以代码中会有一些处理方法:

dir = dir.replace('"','\'').replace(' ','').replace('|','_')

不过这种错误种类太多了,目前只改了这三个

运行配置:大家需要在运行目录下增加一个“jiepai”文件夹,否则就会出现文件夹找不到的错误(暂时想起来这些,要是后面有问题可以评论解决)

运行代码后,大家就可以带自己的"jiepai"文件夹里面看到下面的东西了,点开文件夹,里面就是图片

edc730128eee

爬取成功示例

这里给出项目源码:

import requests

from urllib.parse import urlencode

from multiprocessing import freeze_support

from multiprocessing.pool import Pool

import time

from hashlib import md5

import os

timestamp = int(time.time())

def get_page(offset):

params = {

'aid':'24',

'app_name':'web_search',

'offset':offset,

'format':'json',

'keyword':'街拍',

'autoload':'true',

'count':'20',

'en_qc':'1',

'cur_tab':'1',

'form':'search_tab',

'pd':'synthesis',

#时间戳参数,缺失了也不影响

#'timestamp':timestamp

}

headers = {

'cookie': 'tt_webid=6709993811802818062; WEATHER_CITY=%E5%8C%97%E4%BA%AC; tt_webid=6709993811802818062; UM_distinctid=16bbfdeff8f460-0e02d1b4d98e6d-37607e02-1fa400-16bbfdeff90492; CNZZDATA1259612802=558541297-1562289443-https%253A%252F%252Fwww.google.com%252F%7C1562289443; __tasessionId=aorag2kb71562292191190; csrftoken=e4aae62081d10a9bb97fb5cd48e5cfa7; s_v_web_id=03c096aa5abb1e5a2f9edc5b4be5e8f3'

}

url = 'https://www.toutiao.com/api/search/content/?'+urlencode(params)

try:

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

if response.status_code == 200:

return response.json()

except requests.ConnectionError as e:

print("error",e.args)

return None

def parse_page(json):

if json.get('data'):

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

try:

title = item.get('title')

images = item.get('image_list')

except:

continue

else:

if title is None or images is None:

continue

else:

for image in images:

yield {

'title': title,

'image': image.get('url')

}

def save_image(item):

image =item.get('image')

title=item.get('title')

dir = "jiepai/"+title

#OSError: [Errno 22] 文件名、目录名或卷标语法不正确。: 'jiepai/29张街拍,定格不一样的"空城"纸坊'

#OSError: [Errno 22] 文件名、目录名或卷标语法不正确。: 'jiepai/街拍小技巧|让你的街拍照片秒变时尚大片!'

dir = dir.replace('"','\'').replace(' ','').replace('|','_')

if not os.path.exists(dir):

os.mkdir(dir)

try:

response = requests.get(image)

if response.status_code == 200:

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

print(file_path)

if not os.path.exists(file_path):

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

f.write(response.content)

else:

print('Already Download',file_path)

except requests.ConnectionError:

print('Fail to Save Image')

def main(offset):

print("main",offset)

json = get_page(offset)

for item in parse_page(json):

print(item)

save_image(item)

GROUP_START = 0

GROUP_STOP = 5

if __name__ == '__main__':

freeze_support()

pool = Pool()

group = ([x*20 for x in range(GROUP_START, GROUP_STOP+1)])

print(group)

pool.map(main, group)

pool.close()

pool.join()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值