鱼C论坛

 找回密码
 立即注册
查看: 3487|回复: 2

[作品展示] 抓取今日头条街拍美图

[复制链接]
发表于 2017-3-28 16:42:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 一轮江月明 于 2017-4-7 08:04 编辑

我是跟着崔老师的视频一步一步走的,https://edu.hellobi.com/course/156/lessons
注释很多,都是自己的理解,应该大部分都是对的吧,请各位看出问题的不吝赐教。
有个问题就是,程序不能正确执行,我只是想下载图片到电脑里就行了,现在总是抓不对。

关于求助:
1、一定要提供代码源代码文本,不要只贴图片。(有源码)

2、一定要贴出完整报错信息。(最崩溃的是没有报错信息,是下载了几张图片,可是完全不是那个页面的. 我是新手小白,用pycharm还不会调试,也是被自己笨的哭死了)

3、操作系统,是mac,还是Linux,还是windows。(win)

4、Python 2还是Python 3。(py3)

5、一定要描述清楚,提出问题前,看看自己写的是不是清楚明白。



  1. import requests
  2. from json.decoder import JSONDecodeError
  3. import os
  4. import json
  5. import re
  6. from bs4 import BeautifulSoup
  7. #import pymongo
  8. from requests.exceptions import RequestException
  9. from urllib.parse import urlencode
  10. #from config import *
  11. #from hashlib import md5
  12. #from multiprocessing import Pool

  13. """
  14. client = pymongo.MongoClient(MONGO_URL,connect=False)
  15. db = client[MONGO_DB]
  16. """

  17. def get_page_index(offset, keyword):
  18.     data = {
  19.         'offset': offset,
  20.         'format': 'json',
  21.         'keyword': keyword,
  22.         'autoload': 'true',
  23.         'count': '20',
  24.         'cur_tab': 3
  25.     }

  26.     url = 'http://www.toutiao.com/search_content/?' + urlencode(data)
  27.     print(url)
  28.     '''
  29.     结果是
  30.     url = http://www.toutiao.com/search_content/?offset=0&format=json&keyword=%E8%A1%97%E6%8B%8D&autoload=true&count=20&cur_tab=3
  31.     但是通过这个url只得到了一个json格式的对象,不能得到我们想要的街拍的那个网址(http://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D),
  32.     通过街拍这个网址得到的又是‘综合’,并不是我们想要的‘图集’
  33.     故不能用soup =BeautifulSoup(url.text,'html.parser'),用soup.select('J_title')的方法来得到各个图集的链接地址
  34.     '''
  35.     try:
  36.         response = requests.get(url)
  37.         if response.status_code == 200:
  38.             return response.text        #返回结果是一个字符串
  39.         return None
  40.     except RequestException:
  41.         print('请求索引页出错!')
  42.         return None

  43. def parse_page_index(html):  # 由json对象data得到各图集的地址,并不是由列表页得到各图集的地址,因为没有访问列表页
  44.     try:
  45.         data = json.loads(html)                 # html是一个字符串,data是一个json的对象
  46.         if data and 'data' in data.keys():     # 如果data不为空并且有key:data
  47.             for item in data.get('data'):        # json对象获取字典中键对应值的方法是get,如果是字典,可以直接用dict['key']
  48.                 yield item.get('article_url')     # 得到各图集第一副图的地址
  49.     except JSONDecodeError:                  # json对象为空可能引起的一些错误或者警告
  50.         pass

  51. def get_page_detail(url): #访问每个图集的第一副图的地址
  52.     try:
  53.         response = requests.get(url)
  54.         if response.status_code == 200:
  55.             return response.text
  56.         return None
  57.     except RequestException:
  58.         print('请求索引页出错!')
  59.         return None

  60. def save_image(content,title,num):  # 参数是二进制的图片
  61.     '''
  62.     file_path = '{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg')#每张图片得到一个md5的摘要值,如果图片一样,md5值也会一样
  63.     '''
  64.     file_path = '{0}/{1}.{2}'.format(os.getcwd(),title + '-'+str(num),'jpg')
  65.     if not os.path.exists(file_path):
  66.         with open(file_path,'wb') as f:
  67.             f.write(content)
  68.             f.close()

  69. def download_image(url,title,num):                   #别忘了这个url的内容只有一张图片哦
  70.     print('正在下载',url)
  71.     try:
  72.         response = requests.get(url)
  73.         if response.status_code == 200:
  74.             save_image(response.content,title,num)      #response.text是返回网页的正常显示内容,content是返回二进制内容,一般网页的返回用text,图片的返回用content
  75.         return None
  76.     except RequestException:
  77.         print('请求图片页出错!')
  78.         return None

  79. def parse_page_detail(html, url):#在每个图集的第一副图的地址,即这个页面中找到图集的标题,以及图集所有图片的url
  80.                                  #通过这个url可以真正的访问到第一副图,就可以用beautifulsoup了
  81.     soup = BeautifulSoup(html, 'lxml')                         #用lxml来解析
  82.     title = soup.select('title')[0].get_text()                 #得到网页标签页的标题,一般被title标签包裹(注意不是网页正文内的大标题,
  83.                                                                #正文内的大标题一般被h1或者h2类似的标签包裹),最后如果是.text也可以,
  84.                                                                #一种用属性,一种用方法
  85.     print(title)
  86.     '''
  87.     import requests
  88.     res =requests.get('http://www.toutiao.com/a6402374724713808129/#p=1')
  89.     soup = BeautifulSoup(res.text, 'lxml')
  90.     title = soup.select('title')[0].text                        #这样可以得到标签页title
  91.     title_pattern = re.compile('<title>(.*?)</title>')
  92.     title_result = re.search(title_pattern,res.text)            #可以直接写title_result = re.search('<title>(.*?)</title>',res.text)
  93.     title_result.group(1)                                        #这样也可以得到标签页title
  94.     '''
  95.     images_pattern = re.compile('var gallery = (.*?);', re.S)  # 建立要寻找的字符串的正则表达式模型
  96.     result = re.search(images_pattern, html)                   # 寻找所有符合模型的字符串
  97.     if result:                                                 # 如果result不为空
  98.         data = json.loads(result.group(1))                     # result.group(1)也是一个json对象,包含图片集中每张图片的地址,但是仔细观察会发现,地址有很多重复的,这是怎么回事呢,真的是重复的么?
  99.         if data and 'sub_images' in data.keys():               #字典中得到键的列表集合也是dict1.keys()
  100.             sub_images = data.get('sub_images')                #通过观察结果发现sub_images是一个列表,内容都是字典,有几张图片就有几个字典,字典的第一个键是url
  101.             images = [item.get('url') for item in sub_images]  #images也是一个列表,有几张图片就有几个元素,元素都是url,注意这个url里面的内容只有一张图片
  102.             num = 0
  103.             for image in images:
  104.                 num += 1
  105.                 download_image(image,title,num)
  106.             return {
  107.                 'title': title,   #标签页标题
  108.                 'url': url,       #第一副图的地址
  109.                 'images': images  #这个图集的地址列表
  110.             }
  111.         
  112. def save_to_mongo(result):
  113.     if db[MONGO_TABLE].insert(result):
  114.         print('存储到MongoDB成功',result)
  115.         return True
  116.     return False
  117.    
  118. def main(offset):
  119.     html = get_page_index(offset, '街拍')  # 该访问得到一个包含有个图集地址的json对象(并不是图集列表页)(是图集,不是综合或者视频)的内容,
  120.                                            # html是一个json对象(不是图集列表页)
  121.     for url in parse_page_index(html):     # 由json对象data得到各图集第一副图的地址url
  122.         html = get_page_detail(url)        # 获取各图集第一副图url的正文
  123.     if html:                               # 如果html不为空
  124.             result = parse_page_detail(html, url)
  125.     '''
  126.     if result:save_to_mongo(result)
  127.     '''

  128. if __name__ == '__main__':
  129.     main(0)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2017-3-30 17:43:47 | 显示全部楼层
本帖最后由 一轮江月明 于 2017-3-30 18:05 编辑

今天又写了一遍,我好像知道问题在哪里了

列表页里的各个链接里的内容格式不完全是一样的,所以需要那么多的if判断,有时候请求页面也会出错
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-30 19:34:28 | 显示全部楼层
6、其实非常希望能有人和我一起讨论,一个人学习好孤单。

那你还不快加入Q群528770819。本月最佳答案数量NO1的大神lumber2388779也在这个群哦!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-9-24 04:31

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表