视频地址:
https://edu.hellobi.com/course/156/lessons
还有点小问题,不能正确执行,待解决。
import requests
from json.decoder import JSONDecodeError
import os
import json
import re
from bs4 import BeautifulSoup
#import pymongo
from requests.exceptions import RequestException
from urllib.parse import urlencode
#from config import *
#from hashlib import md5
#from multiprocessing import Pool
"""
client = pymongo.MongoClient(MONGO_URL,connect=False)
db = client[MONGO_DB]
"""
def get_page_index(offset, keyword):
data = {
'offset': offset,
'format': 'json',
'keyword': keyword,
'autoload': 'true',
'count': '20',
'cur_tab': 3
}
url = 'http://www.toutiao.com/search_content/?' + urlencode(data)
print(url)
'''
结果是
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
但是通过这个url只得到了一个json格式的对象,不能得到我们想要的街拍的那个网址(http://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D),
通过街拍这个网址得到的又是‘综合’,并不是我们想要的‘图集’
故不能用soup =BeautifulSoup(url.text,'html.parser'),用soup.select('J_title')的方法来得到各个图集的链接地址
'''
try:
response = requests.get(url)
if response.status_code == 200:
return response.text #返回结果是一个字符串
return None
except RequestException:
print('请求索引页出错!')
return None
def parse_page_index(html): # 由json对象data得到各图集的地址,并不是由列表页得到各图集的地址,因为没有访问列表页
try:
data = json.loads(html) # html是一个字符串,data是一个json的对象
if data and 'data' in data.keys(): # 如果data不为空并且有key:data
for item in data.get('data'): # json对象获取字典中键对应值的方法是get,如果是字典,可以直接用dict['key']
yield item.get('article_url') # 得到各图集第一副图的地址
except JSONDecodeError: # json对象为空可能引起的一些错误或者警告
pass
def get_page_detail(url): #访问每个图集的第一副图的地址
try:
response = requests.get(url)
if response.status_code == 200:
return response.text
return None
except RequestException:
print('请求索引页出错!')
return None
def save_image(content,title,num): # 参数是二进制的图片
'''
file_path = '{0}/{1}.{2}'.format(os.getcwd(),md5(content).hexdigest(),'jpg')#每张图片得到一个md5的摘要值,如果图片一样,md5值也会一样
'''
file_path = '{0}/{1}.{2}'.format(os.getcwd(),title + '-'+str(num),'jpg')
if not os.path.exists(file_path):
with open(file_path,'wb') as f:
f.write(content)
f.close()
def download_image(url,title,num): #别忘了这个url的内容只有一张图片哦
print('正在下载',url)
try:
response = requests.get(url)
if response.status_code == 200:
save_image(response.content,title,num) #response.text是返回网页的正常显示内容,content是返回二进制内容,一般网页的返回用text,图片的返回用content
return None
except RequestException:
print('请求图片页出错!')
return None
def parse_page_detail(html, url):#在每个图集的第一副图的地址,即这个页面中找到图集的标题,以及图集所有图片的url
#通过这个url可以真正的访问到第一副图,就可以用beautifulsoup了
soup = BeautifulSoup(html, 'lxml') #用lxml来解析
title = soup.select('title')[0].get_text() #得到网页标签页的标题,一般被title标签包裹(注意不是网页正文内的大标题,
#正文内的大标题一般被h1或者h2类似的标签包裹),最后如果是.text也可以,
#一种用属性,一种用方法
print(title)
'''
import requests
res =requests.get('http://www.toutiao.com/a6402374724713808129/#p=1')
soup = BeautifulSoup(res.text, 'lxml')
title = soup.select('title')[0].text #这样可以得到标签页title
title_pattern = re.compile('<title>(.*?)</title>')
title_result = re.search(title_pattern,res.text) #可以直接写title_result = re.search('<title>(.*?)</title>',res.text)
title_result.group(1) #这样也可以得到标签页title
'''
images_pattern = re.compile('var gallery = (.*?);', re.S) # 建立要寻找的字符串的正则表达式模型
result = re.search(images_pattern, html) # 寻找所有符合模型的字符串
if result: # 如果result不为空
data = json.loads(result.group(1)) # result.group(1)也是一个json对象,包含图片集中每张图片的地址,但是仔细观察会发现,地址有很多重复的,这是怎么回事呢,真的是重复的么?
if data and 'sub_images' in data.keys(): #字典中得到键的列表集合也是dict1.keys()
sub_images = data.get('sub_images') #通过观察结果发现sub_images是一个列表,内容都是字典,有几张图片就有几个字典,字典的第一个键是url
images = [item.get('url') for item in sub_images] #images也是一个列表,有几张图片就有几个元素,元素都是url,注意这个url里面的内容只有一张图片
num = 0
for image in images:
num += 1
download_image(image,title,num)
return {
'title': title, #标签页标题
'url': url, #第一副图的地址
'images': images #这个图集的地址列表
}
def save_to_mongo(result):
if db[MONGO_TABLE].insert(result):
print('存储到MongoDB成功',result)
return True
return False
def main(offset):
html = get_page_index(offset, '街拍') # 该访问得到一个包含有个图集地址的json对象(并不是图集列表页)(是图集,不是综合或者视频)的内容,
# html是一个json对象(不是图集列表页)
for url in parse_page_index(html): # 由json对象data得到各图集第一副图的地址url
html = get_page_detail(url) # 获取各图集第一副图url的正文
if html: # 如果html不为空
result = parse_page_detail(html, url)
'''
if result:save_to_mongo(result)
'''
if __name__ == '__main__':
main(0)