# -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
import requests
import json
import time
import random
import pymysql
import pandas as pd
from sqlalchemy import create_engine
def fetchURL(url):
'''
功能:访问 url 的网页,获取网页内容并返回
参数:
url :目标网页的 url
返回:目标网页的 html 内容
'''
# headers是为了把爬虫程序伪装成浏览器
headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
# 请求标头中的所有信息都是headers内容,添加到requests请求中
try:
r = requests.get(url,headers=headers) # 发送请求,获取某个网页
r.raise_for_status() # 如果发送了一个错误请求(客户端错误或者服务器错误响应),可以通过r.raise_for_status()来抛出异常
print(r.url)
return r.text
except requests.HTTPError as e: # 如果HTTP请求返回了不成功的状态码,r.raise_for_status()会抛出一个 HTTPError异常
print(e)
print("HTTPError")
except requests.RequestException as e:
print(e)
except:
print("Unknown Error !")
# 抛异常处理
def parserHtml(html):
'''
功能:根据参数 html 给定的内存型 HTML 文件,尝试解析其结构,获取所需内容
参数:
html:类似文件的内存 HTML 文本对象
'''
try:
s = json.loads(html) # json.load()主要用来读写json文件函数:json.loads函数的使用,将字符串转化为字典
except:
print('error')
commentlist = []
hlist = []
# 列表append()方法用于将传入的对象附加(添加)到现有列表中
hlist.append("序号")
hlist.append("名字")
hlist.append("性别")
hlist.append("时间")
hlist.append("评论")
hlist.append("点赞数")
hlist.append("回复数")
#commentlist.append(hlist)
# 楼层,用户名,性别,时间,评价,点赞数,回复数
for i in range(20): # 每页只有20条评论,循环20次
comment = s['data']['replies'][i]
blist = []
floor = comment['floor']
username = comment['member']['uname']
sex = comment['member']['sex']
ctime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(comment['ctime']))
content = comment['content']['message']
likes = comment['like']
rcounts = comment['rcount']
blist.append(floor)
blist.append(username)
blist.append(sex)
blist.append(ctime)
blist.append(content)
blist.append(likes)
blist.append(rcounts)
commentlist.append(blist)
writePage(commentlist)
print('---'*20)
def writePage(urating):
'''
Function : To write the content of html into a local file
html : The response content
filename : the local filename to be used stored the response
'''
# Pandas读取本地CSV文件并设置Dataframe(数据格式),将爬取数据保存到本地CSV文件。加上mode='a' 追加写入数据;sep=','表示数据间使用逗号作为分隔符;不保存列名和行索引
dataframe = pd.DataFrame(urating)
dataframe.to_csv('B_comments.csv', mode='w', index=False, sep=',', header=False)
# 将爬取数据保存到数据库中
conInfo = "mysql+pymysql://root:@localhost:3306/comments?charset=utf8"
engine = create_engine(conInfo,encoding='utf-8')
dataframe.to_sql(name='comment',con=engine,if_exists='append',index=False,index_label='id')
pymysql.connect(host='localhost',port=3306,user='root',passwd='',db='comments',charset='utf8')
# 循环输出9399页,共188454条评论数据内容
if __name__ == '__main__':
for page in range(0,9400):
url = 'https://api.bilibili.com/x/v2/reply?type=1&oid=11357166&pn=' + str(page)
html = fetchURL(url)
parserHtml(html)
# 为了降低被封ip的风险,设置合理的爬取间隔,每爬20页便随机歇1~5秒。
if page%20 == 0:
time.sleep(random.random()*5)