Python3WebSpider / Jiepai

Jiepai Pictures of Toutiao

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

解决了返回data为空、爬取大图、以title命名文件的bug

Anodsaber opened this issue · comments

import requests
from urllib.parse import urlencode
from requests import codes
import os
from hashlib import md5
from multiprocessing.pool import Pool
import re


def get_page(offset):
    headers = {
        'cookie': 'tt_webid=6667396596445660679; csrftoken=3a212e0c06e7821650315a4fecf47ac9; tt_webid=6667396596445660679; WEATHER_CITY=%E5%8C%97%E4%BA%AC; UM_distinctid=16b846003e03d7-0dd00a2eb5ea11-353166-1fa400-16b846003e1566; CNZZDATA1259612802=2077267981-1561291030-https%253A%252F%252Fwww.baidu.com%252F%7C1561361230; __tasessionId=4vm71cznd1561363013083; sso_uid_tt=47d6f9788277e4e071f3825a3c36a294; toutiao_sso_user=e02fd616c83dff880adda691cd201aaa; login_flag=6859a0b8ffdb01687b00fe96bbeeba6e; sessionid=21f852358a845d783bdbe1236c9b385b; uid_tt=d40499ec45187c2d411cb7bf656330730d8c15a783bb6284da0f73104cd300a2; sid_tt=21f852358a845d783bdbe1236c9b385b; sid_guard="21f852358a845d783bdbe1236c9b385b|1561363028|15552000|Sat\054 21-Dec-2019 07:57:08 GMT"; s_v_web_id=6f40e192e0bdeb62ff50fca2bcdf2944',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest',
        'referer': 'https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D',
    }
    params = {
        'aid': '24',
        'app_name': 'web_search',
        'offset': offset,
        'format': 'json',
        'keyword': '街拍',
        'autoload': 'true',
        'count': '20',
        'en_qc': '1',
        'cur_tab': '1',
        'from': 'search_tab',
        'pd': 'synthesis',
    }
    base_url = 'https://www.toutiao.com/api/search/content/?'
    url = base_url + urlencode(params)
    # print(url)
    try:
        resp = requests.get(url, headers=headers)
        if 200  == resp.status_code:
            return resp.json()
    except requests.ConnectionError:
        return None


def get_images(json):
    if json.get('data'):
        data = json.get('data')
        for item in data:
            if item.get('title') is None:
                continue
            title = re.sub('[\t]', '', item.get('title'))
            images = item.get('image_list')
            for image in images:
                origin_image = re.sub("list.*?pgc-image", "large/pgc-image", image.get('url'))
                yield {
                    'image': origin_image,
                    'title': title
                }


def save_image(item):
    img_path = 'img' + os.path.sep + item.get('title')
    if not os.path.exists(img_path):
        os.makedirs(img_path)
    try:
        resp = requests.get(item.get('image'))
        if codes.ok == resp.status_code:
            file_path = img_path + os.path.sep + '{file_name}.{file_suffix}'.format(
                file_name=md5(resp.content).hexdigest(),
                file_suffix='jpg')
            if not os.path.exists(file_path):
                with open(file_path, 'wb') as f:
                    f.write(resp.content)
                print('Downloaded image path is %s' % file_path)
            else:
                print('Already Downloaded', file_path)
    except Exception as e:
        print(e)


def main(offset):
    json = get_page(offset)
    for item in get_images(json):
        save_image(item)


GROUP_START = 0
GROUP_END = 9

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

代码主要修改了以下内容:
1.添加了headers,使返回的json数据的data不为空

headers = {
        'cookie': 'tt_webid=6667396596445660679; csrftoken=3a212e0c06e7821650315a4fecf47ac9; tt_webid=6667396596445660679; WEATHER_CITY=%E5%8C%97%E4%BA%AC; UM_distinctid=16b846003e03d7-0dd00a2eb5ea11-353166-1fa400-16b846003e1566; CNZZDATA1259612802=2077267981-1561291030-https%253A%252F%252Fwww.baidu.com%252F%7C1561361230; __tasessionId=4vm71cznd1561363013083; sso_uid_tt=47d6f9788277e4e071f3825a3c36a294; toutiao_sso_user=e02fd616c83dff880adda691cd201aaa; login_flag=6859a0b8ffdb01687b00fe96bbeeba6e; sessionid=21f852358a845d783bdbe1236c9b385b; uid_tt=d40499ec45187c2d411cb7bf656330730d8c15a783bb6284da0f73104cd300a2; sid_tt=21f852358a845d783bdbe1236c9b385b; sid_guard="21f852358a845d783bdbe1236c9b385b|1561363028|15552000|Sat\054 21-Dec-2019 07:57:08 GMT"; s_v_web_id=6f40e192e0bdeb62ff50fca2bcdf2944',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest',
        'referer': 'https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D',
    }

2.将title中的制表符删掉,避免出现文件名不符合要求的bug

title = re.sub('[\t]', '', item.get('title'))

3.原始的大图URL过期了,于是改成新的形式

origin_image = re.sub("list.*?pgc-image", "large/pgc-image", image.get('url'))
commented

1562907976(1)

这两个链接是指向同一个图片的,按照这个正则应该是没有办法爬到大图的

http://p9-tt.byteimg.com/large/dfic-imagehandler/55304da6-077c-4308-9277-68e5db8bd814
http://p3-tt.byteimg.com/large/dfic-imagehandler/55304da6-077c-4308-9277-68e5db8bd814
指向的又是同一个,所以实际上还是能用

1562907976(1)

这两个链接是指向同一个图片的,按照这个正则应该是没有办法爬到大图的

http://p9-tt.byteimg.com/large/dfic-imagehandler/55304da6-077c-4308-9277-68e5db8bd814
http://p3-tt.byteimg.com/large/dfic-imagehandler/55304da6-077c-4308-9277-68e5db8bd814
指向的又是同一个,所以实际上还是能用

因为large_image_url的写法变了,最早的re表达式匹配不着大图,所以修改了一下

爬了一些图片后出现NotADirectoryError: [Errno 20] 目录名称无效的问题,怎么解决啊?

接口是不是又改了,用requests.get()获取json获取不到,获取的都是
{"count":0,"return_count":0,"query_id":"6537385837821170952","has_more":0,"request_id":"2019080919093101015204407463655ED","search_id":"2019080919093101015204407463655ED","cur_ts":1565348972,"offset":250,"message":"success","pd":"synthesis","show_tabs":1,"keyword":"街拍","city":"北京","tokens":["街拍"],"log_pb":{"impr_id":"2019080919093101015204407463655ED"},"data":null,"data_head":[{"cell_type":79,"forword_search":true,"data_head_type":"data_head_intervention","query":"街拍"}],"ab_fields":null,"latency":675,"search_type":2,"tab_rank":null}

1:根据自己浏览器情况,更改headers里面的内容
2:防止找不到图片报错,修改get_images函数。将‘’‘ images = item.get('image_list')’‘’修改为
if item.get('image_list') is None:
continue
images = item.get('image_list')

getpage(offset)方法里卖弄为什么要传入offset参数?有想交流下爬虫技术的吗?加我微信2761491796

commented

现在今日头条搜索“街拍”返回的结果中包含视频,只爬取图片需要在搜索条件包含has_video=False。其次,image_list字段并不包含文章内的所有图片,如需获取所有图片应该到文章中爬取节点属性为pgc-img的节点内容。2019-8-18

现在又加了时间戳了吧,请问你时间戳是怎么处理的

我用str(round(time.time()*1000))返回的json,data=None 哎苦恼

我用str(round(time.time()*1000))返回的json,data=None 哎苦恼

image
有多个参数timestamp 怎么解决

commented

图片
有多个参数timestamp怎么解决

那是当前时间,不用理会

现在又加了时间戳了吧,请问你时间戳是怎么处理的

不用管的 这个参数不用传 应该是请求的时候自动加上去的

小白复制进去,修改了headers,但是出现了'NoneType' object is not iterable这个错误是怎么回事呀?哪位大佬可以解答一下么?

小白复制进去,修改了headers,但是出现了'NoneType' object is not iterable这个错误是怎么回事呀?哪位大佬可以解答一下么?

我又跑了一遍,确实有个别item出现这个bug,我觉得是因为个别的item在列表页的image_list是空的或者根本没有这个字段,而把图片都放在详情页了。原作者爬取的只是列表页的所有图片,并不包括详情页,所以你可以自行修改代码去爬取详情页图片,或者直接在1楼代码的基础上加点条件判断,把不符合条件的image_list过滤掉。

现在又加了时间戳了吧,请问你时间戳是怎么处理的

时间戳不加也没事啊

getpage(offset)方法里卖弄为什么要传入offset参数?有想交流下爬虫技术的吗?加我微信2761491796

因为这里的offest参数是偏移参数,所以在get_page中我们需要传入每个不同的便宜参数,经过观察每次offest的参数偏移20所以在结尾也写了一个offest增加的这样才能保证爬取每个图片,如果有说错的地方请大佬来纠正一下。

title 含有特殊符号如 | ,“”,...等会导致存入文件时报OSError: [Errno 22] 文件名、目录名或卷标语法不正确。我用replace方法把特殊符号替换成空字符串可以解决部分。请问怎样完全解决这个问题呢?

#新手写的,可以解决图片小的问题,全部是大图。
import time
import os
import requests
from urllib.parse import urlencode
import re
from multiprocessing.pool import Pool

def get_page(offset='0'):
header = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
'x-requested-with' : 'XMLHttpRequest',
'cookie' : 'tt_webid=6759049099767416327; s_v_web_id=50cb5452fa3f2276caa805587827e8dc; WEATHER_CITY=%E5%8C%97%E4%BA%AC; __tasessionId=6vc6yq4br1573713764726; tt_webid=6759049099767416327; csrftoken=406869b194e54be867b653e99f0420f2; sso_auth_status=2e49c25ce425eeb5f379d7f910d312fe; sso_uid_tt=a53e62d2487d6b44d3c448d3c4dc19af; toutiao_sso_user=0d36fe1b94b02fd6d70710560abb2cb0; passport_auth_status=ce1d8e6e49f64766db03a8a391fad194%2C920cde7d62aef314d95ac31283bb79e2%2C; sid_guard=71c050139a9d4f21d90ba4cb7b7a64d6%7C1573715788%7C5184000%7CMon%2C+13-Jan-2020+07%3A16%3A28+GMT; uid_tt=051bd643bff25ce4248e84ad71f116dd; sid_tt=71c050139a9d4f21d90ba4cb7b7a64d6; sessionid=71c050139a9d4f21d90ba4cb7b7a64d6; cp=5DCC2F8F05828E1',
'referer': 'https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D'
}
params = {
'aid' : '24',
'app_name' : 'web_search',
'offset' : offset,
'format' : 'json',
'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(params)
try:
response = requests.get(url, headers=header)
if response.status_code == 200:
return response.json()
except requests.ConnectionError:
return None

def get_images(json):
if json.get('data'):
data = json.get('data')
for item in data:
if 'title' not in item: #有些data标签没有title,这是排除不然会报错
continue
title = re.sub('[\t"“”]', '', item.get('title'))
#文件名不能有特殊字符,这里全部替换为这字符
images = item.get('image_list')
for image in images:
yield{
'title' : title,
'image_url' : image.get('url')
}

def save_images(item):
if not os.path.exists(item.get('title')):
os.mkdir(item.get('title'))

origin_url = item.get('image_url')
url = re.sub('list/190x124|list', 'origin', origin_url)
#我看了很多图片URL,发现最好的不是large,而是origin,图片url有两种,两种都要改
r = requests.get(url)
path = '{}'.format(item.get('title'))
image_name = url.split('/')[-1] + '.jpg'
file_name = path + '\\' + image_name
with open(file_name, 'wb') as f:
    f.write(r.content)
print('下载{}.....'.format(image_name))

def main(offset):
json = get_page(offset)
if not os.path.exists('jiepai'):
os.mkdir('jiepai') #这里我是把文件下载在这个py文件所在目录的jiepai目录下
os.chdir('jiepai')
t1 = time.time()
for item in get_images(json):
save_images(item)
print('下载完成')
t2 = time.time()
print(t2 - t1) #加了个记时的东西,主要是看不懂多线程,所以我加这个是为了比一比哪个快,我下载2页用8分钟

if name == "main":
pool = Pool() #这是模仿别人这样写的,我也不懂多线程,才学
groups = [x*20 for x in range(2)] #这个 2 可以改,指前n页内容
pool.map(main, groups)
pool.close()
pool.join()

不知道怎么上传代码才能和楼主的一样,有缩进

构建基础链接
多了一个timestamp:1573874975248
每次刷新网页数值是不一样的 ,然后ajax 下拉加载的值也没有规律

有规律,请注意offset值的变化,timestamp 可以忽略,或者 timestamp = str(int(time.time()*1000)) 构造出来,注意要导入time模块

title 含有特殊符号如 | ,“”,...等会导致存入文件时报OSError: [Errno 22] 文件名、目录名或卷标语法不正确。我用replace方法把特殊符号替换成空字符串可以解决部分。请问怎样完全解决这个问题呢?

    try:
        save_image(item)
    except Exception as e:
        continue

报错直接跳过这个title即可。鸵鸟战术

怎么爬取详情页中的高清大图啊

下载终止:错误如下

FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。:

The above exception was the direct cause of the following exception:

为什么这个代码在pycharm跑起来没有报错,但是没有显示爬取的文件信息?初学python的小白很多地方不太明白,求赐教

? 来自大洋彼岸的朋友?  

------------------ 原始邮件 ------------------ 发件人: "verse322"<notifications@github.com>; 发送时间: 2019年12月16日(星期一) 下午3:33 收件人: "Python3WebSpider/Jiepai"<Jiepai@noreply.github.com>; 抄送: "X J"<641535181@qq.com>;"Comment"<comment@noreply.github.com>; 主题: Re: [Python3WebSpider/Jiepai] 解决了返回data为空、爬取大图、以title命名文件的bug (#21) 为什么这个代码在pycharm跑起来没有报错,但是没有显示爬取的文件信息?初学python的小白很多地方不太明白,求赐教 — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

身在祖国西部ing 求教大佬上面的问题

timestamp没写 ?我记得我之前没加timestamp就爬不到东西

------------------ 原始邮件 ------------------ 发件人: "verse322"<notifications@github.com>; 发送时间: 2019年12月16日(星期一) 下午3:45 收件人: "Python3WebSpider/Jiepai"<Jiepai@noreply.github.com>; 抄送: "X J"<641535181@qq.com>;"Comment"<comment@noreply.github.com>; 主题: Re: [Python3WebSpider/Jiepai] 解决了返回data为空、爬取大图、以title命名文件的bug (#21) ? 来自大洋彼岸的朋友?   … ------------------ 原始邮件 ------------------ 发件人: "verse322"<notifications@github.com>; 发送时间: 2019年12月16日(星期一) 下午3:33 收件人: "Python3WebSpider/Jiepai"<Jiepai@noreply.github.com>; 抄送: "X J"<641535181@qq.com>;"Comment"<comment@noreply.github.com>; 主题: Re: [Python3WebSpider/Jiepai] 解决了返回data为空、爬取大图、以title命名文件的bug (#21) 为什么这个代码在pycharm跑起来没有报错,但是没有显示爬取的文件信息?初学python的小白很多地方不太明白,求赐教 — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe. 身在祖国西部ing 求教大佬上面的问题 — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

有这个问题 刚刚调试成功 感谢!

commented

2019/12/27
解决爬取不到数据的问题:加上时间戳,headers换成自己的cookie,user-agent,referer,问题解决。