Python3WebSpider / Jiepai

Jiepai Pictures of Toutiao
124 stars 142 forks source link

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

Open Anodsaber opened 5 years ago

Anodsaber commented 5 years ago
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'))
Null-Bot9875 commented 5 years ago

1562907976(1)

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

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

Anodsaber commented 5 years ago

1562907976(1)

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

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

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

wjw1379321500 commented 5 years ago

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

Jianyang1000 commented 5 years ago

接口是不是又改了,用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}

JwDong2019 commented 5 years ago

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

yesxcv commented 5 years ago

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

lipeng12138 commented 5 years ago

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

lisilpython commented 5 years ago

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

lisilpython commented 5 years ago

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

lisilpython commented 5 years ago

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

838957471 commented 5 years ago

image 有多个参数timestamp 怎么解决

lisilpython commented 5 years ago

举个例子

------------------ 原始邮件 ------------------ 发件人: "CUG_ZuChuan Huang"notifications@github.com; 发送时间: 2019年9月4日(星期三) 下午4:25 收件人: "Python3WebSpider/Jiepai"Jiepai@noreply.github.com; 抄送: "X J"641535181@qq.com;"Comment"comment@noreply.github.com; 主题: Re: [Python3WebSpider/Jiepai] 解决了返回data为空、爬取大图、以title命名文件的bug (#21)

有多个参数timestamp 怎么解决

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

Fish1874 commented 5 years ago

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

那是当前时间,不用理会

HIT-Owen commented 5 years ago

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

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

GlamyX commented 5 years ago

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

Anodsaber commented 5 years ago

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

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

Anodsaber commented 5 years ago

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

时间戳不加也没事啊

NeighborOldSheep commented 4 years ago

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

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

ASanlittleboss commented 4 years ago

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

yao5201478 commented 4 years ago

新手写的,可以解决图片小的问题,全部是大图。

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

yao5201478 commented 4 years ago

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

yao5201478 commented 4 years ago

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

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

timor1988 commented 4 years ago

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

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

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

DonkeyL commented 4 years ago

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

DonkeyL commented 4 years ago

下载终止:错误如下

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

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

verse322 commented 4 years ago

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

lisilpython commented 4 years ago

?

来自大洋彼岸的朋友?  

------------------ 原始邮件 ------------------ 发件人: "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.

verse322 commented 4 years ago

? 来自大洋彼岸的朋友?   ------------------ 原始邮件 ------------------ 发件人: "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 求教大佬上面的问题

lisilpython commented 4 years ago

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.

verse322 commented 4 years ago

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.

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

YanRuYu123 commented 4 years ago

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