爬取备份“忧郁的弟弟”站点Galgame

Rhilip 2018-08-07 PM 13482℃ 17条

我的Galgame资源发布站 - 忧郁的弟弟 是由忧郁的弟弟提供的汉化Galgame下载站点,关于该站点介绍请访问:关于若干注意事项(新人必读) | 我的Galgame资源发布站

资源备份档分享请见:Mygalgame全站资源备份
他人抓取项目请见: Mygalgame backup

弟弟站点html结构十分规范,而且爬取特别容易。问题在于该站的资源都是用百度云进行存储,而百度云的转存与下载较为麻烦。这里我们采取抓取和转存分别进行的方法,构造备份站点。步骤如下:

  1. 对弟弟站所有页面进行抓取下载并存储。
  2. 进行百度云批量转存,使用BaiduPCS-GO进行下载操作。
  3. 使用rclone转存到GDrive以及OneDrive。
  4. 使用OneIndex进行展示~

关于“忧郁的弟弟”站点备份,Github已有类似项目,具体可参见:Beats0/www.mygalgame.com

站点爬取

目前弟弟站的百度云链接需要使用post的方式二次获取,故在获取到文章链接后,构造post表单进行获取。方法如下:

import re
import time
import sqlite3
import requests
from bs4 import BeautifulSoup

s = requests.Session()
s.cookies.update({"switchtheme":"mygalgame2"})
s.headers.update({"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"})

db = sqlite3.connect(r"f:/mygalgame.db")
cur = db.cursor()

cur.execute("CREATE TABLE mygalgame ("+
    "raw_link   VARCHAR (255),"+
    "name       VARCHAR (100),"+
    "baidu_link VARCHAR (255),"+
    "secret_key VARCHAR (4)   UNIQUE PRIMARY KEY,"+
    "descr      TEXT"+
");"
)

for p in range(1,84):
    page = s.get("https://www.mygalgame.com/page/{}/".format(p))
    page = BeautifulSoup(page.text,"lxml")
    a_list = page.select("div#article-list > div > section > div.title-article > h1 > a")
    article_list = list(map(lambda x:x["href"], a_list))
    print("Craw Page {}, and find {} links".format(p,len(article_list)))
    for a in article_list:
        page_1 = s.get(a)
        if re.search("A\d{3}",page_1.text):
            secret_key = re.search("A\d{3}",page_1.text).group(0)
            page_2 = s.post(a,data={"e_secret_key":secret_key})
            page_bs = BeautifulSoup(page_2.text,"lxml")
            name_ = page_bs.select_one("div.title-article a").get_text()
            baidu_link = re.search("go\.php\?url=(https?://pan.baidu.com/s/[^']+)'",page_2.text).group(1)
            descr = str(page_bs.select_one("div.centent-article"))
            descr = descr[:descr.find("<!-- 内容主体结束 -->")]
            cur.execute("INSERT INTO `mygalgame` (`raw_link`, `name`, `baidu_link`, `secret_key`, `descr`) VALUES (?,?,?,?,?)",(a,name_,baidu_link,secret_key,descr))
            print("{}: {} OK~".format(secret_key,a))
            db.commit()
        time.sleep(5)
    print("Page {} Over~".format(p))
    time.sleep(5)

经过上述爬取,仍发现几项缺失,具体列在下表:

缺失项可能的名称备注
A345*资源吃饭没找到~
A457下级生2与下级生1(A456)同一页面
A458恋×シンアイ彼女 体験版正式版见A584
A516オトメ*ドメイン 体験版参见他人备份补齐
A574千恋*万花手动补齐

百度云转存下载

使用Selenium半自动登陆并转存。代码如下,前半部分登陆手动完成,后面分享转存交由程序进行。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

browser = webdriver.Chrome(r"d:\chromedriver.exe")
browser.get("https://pan.baidu.com")  # 用户登陆(手动)

uk_list = cur.execute("SELECT baidu_link,secret_key from mygalgame order by secret_key asc").fetchall()
for url,key in uk_list:
    try:
        browser.get(url)   # 打开分享链接
        browser.implicitly_wait(3)   # 等待3秒
        browser.find_element_by_tag_name("input").send_keys(key,Keys.ENTER)  # 输入分享密码并回车
        browser.implicitly_wait(5)
        browser.find_element_by_xpath('//*[@id="shareqr"]/div[2]/div[2]/div/ul[1]/li[1]/div/span[1]').click()  # 全选分享文件
        browser.find_element_by_xpath('//*[@id="bd-main"]/div/div[1]/div/div[2]/div/div/div[2]/a[1]/span/span').click()  # 点击转存按钮
        browser.implicitly_wait(2)
        browser.find_element_by_xpath('//*[@id="fileTreeDialog"]/div[3]').click()  # 勾选上次保存位置
        browser.implicitly_wait(2)
        browser.find_element_by_xpath('//*[@id="fileTreeDialog"]/div[4]/a[2]/span').click()  # 点击确认按钮
        browser.implicitly_wait(2)
        print("Transfer {}#{} Success~".format(url,key))
    except Exception:
        print("Transfer {}#{} Fail!!!!".format(url,key))

TIM截图20180806131047.jpg

注意:

  • 估算每个Gal的体积为2G,故1T百度云盘约能转存500左右游戏。
  • 请使用开发者工具block掉一些请求,以防止页面长时间等待加快速度。例如:

TIM截图20180806113155.jpg

而下载使用 BaiduPCS-GO。使用前面获取的BUDSS进行登陆,并使用screen挂在后台进行下载即可。(然而使用国外服务器下载还是很慢23333)

简介清洗

因为OneIndex能展示READMD.md,所以将原有html格式简介清洗为markdown格式的文件,示例格式如下:

import subprocess
import sqlite3
import re

from markdownify import markdownify as md
from bs4 import BeautifulSoup

process = subprocess.Popen(['rclone','lsd','GDrive:/galgame'], stdout=subprocess.PIPE)
output, _  =process.communicate()

output = str(output,"utf-8")

outlist = output.splitlines()

db = sqlite3.connect(r"f:/mygalgame.db")
cur = db.cursor()

temple = """
# {name}

> 来源于: [{source_link}]({source_link})

## 游戏截图

{img_list}

## 游戏简介

{introduce}

## 汉化STAFF

{staff}


## 文件信息

备注: {beizhu}

{note}

标签: {tag}
"""


for i in outlist:
    oid = re.search("A\d{3}",i).group(0)

    print("开始处理{}".format(i))

    sourcename = re.search("A\d{3}.*?$",i).group(0)

    fetch_ = cur.execute("SELECT * FROM mygalgame where secret_key = ? ",[oid])
    link,name,bdlink,key,descr,_ = fetch_.fetchone()

    de_bs = BeautifulSoup(descr,"lxml")
    img_list = de_bs.find_all("img")
    img_md = "\n".join(map(lambda x:"![]({})".format(x["src"]),img_list))

    introduce = staff = beizhu  = tag =  ""

    main_part = de_bs.find_all("div",class_="alert-success")

    if len(main_part) == 1:
        i_tag = main_part[0]
        introduce = md(str(i_tag))
    elif len(main_part) > 1:
        i_tag,s_tag = main_part[:2]
        staff = md(str(s_tag))
        introduce = md(str(i_tag))

    beizhu_search = re.search('备注:<span style="color: #ff0000;">(.+?)</span>',descr)
    if beizhu_search:
        beizhu = beizhu_search.group(1)

    tag_list_raw = de_bs.find_all("a",rel="tag")
    if len(tag_list_raw) > 0:
        tag_list = map(lambda x:x.get_text(strip=True),tag_list_raw)
        tag = ", ".join(tag_list)


    note = md(str(de_bs.find("div",class_="alert-info"))).replace("任何解压相关问题请看网站顶部解压必读,不看而发问直接小黑屋","").strip()

    md_data = temple.format(name=name,source_link=link,img_list=img_md,introduce=introduce.replace("\n","\n\n"),
    staff=staff.replace("\n","\n\n"),note=note.replace("\n","\n\n"),beizhu=beizhu,tag=tag)
    print("生成的Markdown格式如下",md_data)

    with open(r"F:\Temp\README.md","w",encoding="utf-8") as f:
        f.write(md_data)
        print("写入临时文件完成")

    process = subprocess.Popen(['rclone','copy',r"F:\Temp\README.md",'GDrive:/galgame/{}'.format(sourcename)], stdout=subprocess.PIPE)
    process.communicate()
    print("上传 README.md 完成")

    dstname = "{}@{}".format(key,name)
    process = subprocess.Popen(['rclone','moveto','GDrive:/galgame/{}'.format(sourcename),'GDrive:/mygalgame/{}'.format(dstname)], stdout=subprocess.PIPE)
    process.communicate()
    print("文件夹 重命名+移动 完成")

OneIndex建站

随意找一个微软5T的盘,绑定OneIndex进行展示,使用rclone将Google Drive上面的文件夹完全转发。

标签: Python, sqlite3, mygalgame

非特殊说明,本博所有文章均为博主原创。

评论啦~



已有 17 条评论


  1. 全班最弱的女生
    全班最弱的女生

    个人感觉 Selenium 这种神器 只在对网站实在没办法爬到数据了,最后才祭出 Selenium ,一般用 scrapy 就够了

    回复 2018-09-20 07:53
    1. Rhilip
      Rhilip 博主

      爬取过程本来就没有用selenium呀,直接requests模拟发包的。当然你说的是git上面那个备份项目另说。Selenium在此文中主要处理百度云转存,这个使用requests模拟过于麻烦,scrapy这种纯抓取的肯定不能用。。

      回复 2018-09-20 14:40
  2. 小火柴
    小火柴

    现在忧郁的弟弟里需要输入图片验证码才能显示网盘链接,想请教一下这种情况下只能通过识别图片验证码得到答案加到post请求里才行吗?请问还有没有其他的处理方法获得网盘链接呢?

    回复 2018-11-23 10:13
    1. Rhilip
      Rhilip 博主

      是,直接上验证码识别吧。3位纯数字还是很简单就能破解的。旧档可以找Github上某人的备份,直接clone整个项目。

      回复 2018-11-23 15:09
  3. DB
    DB

    请问如何能够一次性大量下载新版OneDrive中的文件(夹),有支持断点续传以及多线程的方式吗?谢谢。

    回复 2019-10-12 17:06
    1. Rhilip
      Rhilip 博主

      目前没有找到

      回复 2019-10-12 20:34
  4. miko
    miko

    你去看一下他网页的js就知道写这个爬虫是多余的。他外放了一个galgameList接口,直接有所有游戏的下载地址、页面地址、游戏名、游戏类型。js文件名是fade.js,接口为..。这个js里包含了游戏列表的json接口和所有背景图的地址

    回复 2019-12-10 02:10
    1. Rhilip
      Rhilip 博主

      那你知道不知道一年前有没有这个接口那?
      看来是我错怪你了,你连mygalgame的主站是哪个都不知道。
      https://beats0.github.io/www.mygalgame.com/Game_list/mygalgameList.json
      这个上面的数据也是爬虫抓出来的。

      回复 2019-12-10 10:05
  5. null
    null

    大佬,有没有办法爬背景图片啊,好像是加密的

    回复 2020-01-11 22:07
  6. kjlx
    kjlx

    大佬,你分享的文件有没有办法能转存到自己的onedrive,直接下载好像不太现实

    回复 2020-01-23 00:54
  7. Konnyaku
    Konnyaku

    [email protected]~辉之季节~OneDrive下载了三遍,检查md5均与期望值不同:
    OneDrive下载的md5:ba942e8ca9f2e41eecac8c8460773d33
    期望值:7EA93EBBB14A53A8BC24EA1587003AD0

    回复 2020-03-12 10:18
    1. Konnyaku
      Konnyaku

      emm......似乎是弟弟本身的问题

      回复 2020-03-12 10:42
    2. Rhilip
      Rhilip 博主

      弟弟那边现在也提供OneDrive了,有些从他那下载可能更好些。(比以前要从百度下方便多了)
      我这里的存档很久没有更新过了,有些他后面有更新我没同步。

      回复 2020-03-12 11:11
  8. oeasy
    oeasy

    您好,资源备份的短链接失效了,考虑补一下链嘛?

    回复 2020-04-22 09:30
  9. 嚒嚒嚒呐
    嚒嚒嚒呐

    友嘎哒!轰动你阿里嘎多。

    回复 2020-05-09 09:45
  10. 嚒嚒嚒呐
    嚒嚒嚒呐

    找不到捐赠项呢,请你吃顿快餐~(15rmb)

    回复 2020-05-09 09:53
  11. leung
    leung

    請問资源备份網站是不是關了QQ
    連不上去..

    回复 2020-06-09 17:06