下载了上百个RJ后,如何根据声优或分类喜好来找到自己喜欢的作品就成了个问题,于是诞生出了这个代码
问题拆分
定位需求
查询RJ主要是在对该RJ文件夹对应网页中的标题、声优、制作社团与分类,拿到具体数据后,对数据进行查询操作。
大致方法
遍历RJ文件所在的文件夹可以使用os,提取其中的RJ号可使用re正则表达式,根据提取到的RJ号使用request模块模拟打开网站,再使用bs4对标题、声优、制作社团、分类进行提取,提取的数据保存乳本地mysql数据库中方便查询,此处使用MySQLdb库
代码
import requests
from bs4 import BeautifulSoup
import re
import os
import MySQLdb
def get_url(rj):
url='https://www.dlsite.com'
req_link= url + "/maniax/work/=/product_id/{}.html"
url_rj=req_link.format(rj)
return url_rj
def get_html(url):
headers = {
'Host':'www.dlsite.com',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Referer':'https://www.dlsite.com/maniax/',
'Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'Accept-Encoding':'gzip, deflate, br',
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
}
response=requests.get(url,headers=headers)
dl = BeautifulSoup(response.text,'html.parser')
return dl
#第一次响应返回的html中,’h1‘标签中的标题,返回结果为标题字符串
def get_title(html):
i=html.find('h1')
if i:
title=str.strip(i.get_text())
if title == '':
return '不明'
else:
return title
else:
return '不明'
def get_maker(html):
i=html.find(itemprop="brand")
if i:
maker=str.strip(i.get_text())
if maker == '':
return '不明'
else:
return maker
else:
return '不明'
def get_seyuu(html):
seyuu=html.find(id="work_outline")
if seyuu:
s=str.strip(seyuu.get_text())
i=re.findall(r'[声][优][\n]+[^\n]+[\n]{2}',s)
if i == []:
return '不明'
else:
b=i[0].replace('\n','').replace('声优','').replace(' ','')
return b
else:
return '不明'
def get_genre(html):
g=html.find(class_="main_genre")
if g:
genre=str.strip(g.get_text())
if genre == '':
return '不明'
else:
return genre
else:
return '不明'
def check_rj(rj):
host = ('localhost')
user = ('root')
pass_ = ('123456')
db = ('sqlforpy')
connect = MySQLdb.connect(host,user,pass_,db,charset='utf8')
cursor = connect.cursor()
sql = 'SELECT RJ FROM infor_voice'
cursor.execute(sql)
result = cursor.fetchall()
rj_ = []
n_ = 0
for i in rj:
r_=(i,)
if r_ not in result:
rj_.append(i)
n_ += 1
elif r_ in result:
print('%s已存在'%i)
print('将写入%d条信息'%n_)
return rj_
def sql(rj,title,seyuu,maker,genre):
host = ('localhost')
user = ('root')
pass_ = ('123456')
db = ('sqlforpy')
connect = MySQLdb.connect(host,user,pass_,db,charset='utf8')
cursor = connect.cursor()
sql = """insert into infor_voice(RJ,标题,声优,社团,分类)VALUES\
("%s","%s","%s","%s","%s")"""% (rj,title,seyuu,maker,genre)
try:
cursor.execute(sql)
connect.commit()
except:
print('%s写入数据库出现错误!'%rj)
connect.rollback()
connect.close()
def get_rj(path):
list_=[]
for root,dirs,files in os.walk(path):
for i in dirs:
if i.strip().startswith('RJ'):
rj=re.findall('[Rr][jJ][0-9]+',i)[0]
list_.append(rj)
return list(set((list_)))
def run_(path):
print('查重开始')
rj=check_rj(get_rj(path))
print('查重结束')
for i in rj:
print('开始搜索%s'%i)
url=get_url(i)
html=get_html(url)
sql(i,get_title(html),get_seyuu(html),get_maker(html),get_genre(html))
print('%s保存完毕'%i)
print('结束')
if __name__ == "__main__":
path=r'H:\Down\For\Ad'
run_(path)
一些笔记
本地RJ中使用了list(set(list))方法对提取到的RJ号进行去重复,在爬取前还先将数据库中原本存在的RJ号进行提取并与本地文件夹中的RJ号对比,提取非重复部分进行第二次去重,减少爬取数量。
有些RJ作品下架导致无法查询具体信息,将返回“不明”作为补充(此处代码可简化),还有RJ作品中无声优或社团信息,也将返回“不明”(此处有待优化)
写入本地数据库中,若因未知错误出现无法写入的状况将提示出错,并显示具体RJ号
一些问题
- 下架作品查询重复,浪费时间
- 声优信息也出现在作品描述里面,可进行替代
- 无法反向对只有RJ号的本地文件夹进行命名操作
- 只有标题而无RJ前缀的文件夹将无法查询
- 后续补齐无法对本地数据库进行批量修改更新