// ==UserScript== // @name 豆瓣评分增强大师 // @namespace doveboy_js // @version 10.89 // @description 一站式聚合全球数十家主流影视数据库与评分平台,涵盖IMDb、烂番茄新鲜度&爆米花指数、Metacritic影评人&用户双评分、TMDB、Letterboxd、Allocine、AniList、Bangumi、MyAnimeList、MyDramaList、NeoDB及Common Sense Media等,全面覆盖电影、剧集、综艺与动画四大类型。独家打造“客观评分”智能加权算法,依据作品主场自动调权,融合票数置信度输出一个真正去偏的综合分数,并创新引入Steam式好评率分析,将豆瓣影评拆解为总评、热门、最新三维好评度,让口碑一目了然。自动拉取出品发行、技术参数、幕后花絮及获奖荣誉,并以悬浮气泡优雅展示;同步联动电影票房,实时汇率换算呈现预算、全球票房、北美首周、大陆首周&总票房及港台日韩等细分市场收支全景卡片。特有“大中华区评分差异对比”横评两岸三地观众口味分歧,辅以剧集播出日历,更提供一键复制影片资料(含完整演职员表及获奖列表)与历史评分趋势曲线,让每一部作品的轮廓在豆瓣页面上从未如此立体、专业而丰沛。 // @author 白鸽男孩 // @contributor Rhilip // @license Zlib/Libpng License // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAQAElEQVR4AezcW3rbOpYGUKaHUHXm08ms8mbnLbM67vmcqiEkvbciJb7IsiSCxG3lEyNbFoGNBYq/CDn5n8UfAgQIECBwh4AAuQPNLgQIECCwLALEUUCgloB+CXQuIEA6n0DlEyBAoJaAAKklr18CBAh0LtBxgHQur3wCBAh0LiBAOp9A5RMgQKCWgACpJa9fAh0LKJ1ACgiQVLARIECAwM0CAuRmMjsQIECAQAoIkFTYe9MfAQIEBhAQIANMoiEQIECghoAAqaGuTwIEagnot6CAACmIqSkCBAjMJCBAZpptYyVAgEBBAQFSEHOGpoyRAAECJwEBcpK44/6vr8tnGwPHQN/HwB0vfbscBQTIEeLc3enE8K+vy+O/vy5/5xZf/zxtP5blbxsDx0Dfx8Dp9Zz3x9f4Y3x92PIccO7cUOex9noVIMc5yQMltzyAcosD6OfpxBBPefi5LJ9zi6/dCBAYVOD4Gn+I4R22PAfkueC4HUIlfuZ2FJg6QJ4HRh4oueUBlNvRxx0BAgROAodQOYZJrkRMHyjTBcgpNPIgEBin18UU9wZJoLTA80B5zHNL6Q5ab2+KAMmJjcA4fI5xCo3WJ0Z9BAh0JfCQ55Y4zxyuTLqqfEWxQwdIBkd+npETG0aHzzHi3o0AAQJbCjycgiTPQVt2VLvtqwOkdqG39J+TdgoOn2fcIue5BAgUFDhdlQz7WclQASI4Ch76miJAoJTA6bOS4YJkmABxxVHqWNdOewIqGkTgd5AMMp6l+wCJtcZM9Z+WqkY5JI2DwPACvz8j6X2k3QbIabkqJiBTPe7cCBAg0JXAQ66c5Jvgrqp+VmyXAZLg+ZtVV151PBuuLwkQINCOwPEcllckj+1UdX0lXQWIq47rJ9YzCRDoSuBwNdJVxVFsNwGS4eGqI2bMjUBPAmq9WiCvRmJ1pat/iNhFgATqY4bH1TPhiQQIEOhXoJslreYDJD9kiuPAB+WB4EaAwDQCXYRI0wGS4ZGXddMcMm8G6gECBCYWaP5zkWYDRHhM/LIxdAIEDgL5BjrPhYdvGvyruQDJD8vjMw//MLDBg0VJBGYSaGWsGSJ5TsxzYys1nepoKkASyIflp6lxT4AAgT8CeW7Mc+SfR+p/1VSAJFB9EhUQIECgTYHWzpHNBEjL63xtHkqNV6U8AgQ2EWjpXNlEgCRIrvNtoq1RAgQIDCSQ58o8Z7YwpOoBEh8OPSZICxhqIECAQA8Cec68ECK7DaFqgGR4xEj9I8FAcCNAgMAtAhkix3PoLbsVfW61ADkOXHgUnU6NESAwmcBDzd/MqhYgMcnCIxDc2hNQEYGeBPI3s2qFSJUAaWHtrqcDRK0ECBC4JBDLWVXekO8eILl0FYP9fAnDzwgQIEDgeoE8p+a59fo9yjyzfIBcqOs4wCpJeaEsPyJAgMAIArt/HrJrgHxalv8dYZaMgQABAi0KxJXIrm/QdwuQvPqIwVm6avGoU9MoAsYxuUCeY/NcuxfDbgESA9o1GaM/NwIECMwosNu5dpcA2TMRZzxajJkAAQLPBfb6TdfNA+QYHrsl4nPEW7/2fAIECIwgkEtZe/zbkM0DZITJMAYCBAj0JhAhsvkb900DxNVHb4ecegnUEtBvaYEIkM9bX4VsGiClQbRHgAABAtcLRIhsehWyWYAck2/T4q9n9EwCBAjMJxABsulVyGYB8mNZ/JuPZbc/OiJAgMBZgQiRzd7IbxYgMZLNio623QgQIEDgCoEIkM2uQjYJkOOH51cMzVMIECDQuUAH5W+1IrRJgISnq49AcCNAgEALAlv9P4TFA+T44XkLZmogQIAAgRDYahmreIBsdakUBm5DChgUAQJ7CESIFF8ZKh4gAVG8yGjTjQABAgRWCESAFP/N2KIB4sPzFbNrVwIECGws8PojhrXdFQ2QtcXYnwABAgS2E4irkKIrRKUDpGhx2zFqmQABAgTWCpQOkLX12J9APwIqJdCZQFyBFP1HhcUCxOcfnR1JyiVAgMBKgWIBsrIOuxMgQIDADgJxFVLso4aSAXJjUTtI6YIAAQIENhMoGSCbFalhAgQIECgjEFcgxf49SJEAKf27xWWYtEKAwHsCHp9boNQ5u0iA+O9L5j4YjZ4AgTkFigTInHRGTYAAgT4FSr3pFyD3zL99CBAg0LFAqf/evUiAlCqm4/lQOgECBKYTKBIgJT/Vn24GDJgAgVsEPLeAQKlzdpEAKTAeTRAgQIBAZwICpLMJUy4BAgRaEVgdIKV+n7gVkNHrMD4CBAikQIlz9+oAyUJsBAgQIDCfgACZb86NmACBKgLjdSpAxptTIyJAgMAuAgJkF+brO4kJ+WJbGCwMzr0Orn8leeYeAjFHe3Sjj2sF/vm+PNnOGnBxbDxd+zryvH0EBMg+znohQIDAcAICZLgpNSACBAgUFninOQHyDoyHCRAgQOCygAC57OOnBAgQIPCOgAB5B8bDBMoJaInAmAICZMx5NSoCBAhsLiBANifWAQECBMYU6CFAxpQ3KgIECHQuIEA6n0DlEyBAoJaAAKklr18CPQiokcAFAQFyAcePCBAgQOB9AQHyvo2fECBAgMAFAQFyAWf9j7RAgACBcQUEyLhza2QECBDYVECAbMqrcQIEagnod3sBAbK9sR4IECAwpIAAGXJaDYoAAQLbCwiQ7Y377EHVBAgQ+EBAgHwA5McECBAgcF5AgJx38SgBAgRqCXTTrwDpZqoUSoAAgbYEBEhb86EaAgQIdCMgQLqZKoVeK+B5BAjsIyBA9nHWCwECBIYTECDDTakBESBAYB+BtwGyT796IUCAAIHOBQRI5xOofAIECNQSECC15PVL4K2ARwh0JSBAupouxRIgQKAdAQHSzlyohAABAl0JDBUgXckrlgABAp0LCJDGJvCvr8tnGwPHwPljoLGX6/TlCJDGDoEfy/K3jUF/x8A+c9bYy3X6cgTI9IcAAAIECNwnIEDuc7MXAQIEphcQIG0cAqogQIBAdwICpLspUzABAgTaEBAgbcyDKggQqCWg37sFBMjddHYkQIDA3AICZO75N3oCBAjcLSBA7qaz4y8BfxMgMKuAAJl15o2bAAECKwUEyEpAuxMgQKCWQO1+BUjtGdA/AQIEOhUQIJ1OnLIJECBQW0CA1J4B/dcT0DMBAqsEBMgqPjsTIEBgXgEBMu/cGzkBAgRWCawIkFX92rmgwKdleVqW5VtuMaFfbAuDpT2DPD5fbfGtW88Cca7pufx5a8/QiMn78t/vy6f/fF/y/jG+fvzn+/JkY9DiMZDH56vtUx7D8SrONz9x59abQMxfbyVPX++3eBEeQiNPEtNrTAowyrDzGI7jOd/8xHuiw1X0KEObYhwCpJNpjlfXU0zW4Uqjk5KVSeAmgVOQ5LF+046eXE0gzknV+tbxlQL5gsplqny3duUunkagW4E81qN4y1qB0PptzgBpfVZe1vft+IJ6+ajvCAwskFcjMTwhEggt3wRIw7OTVx7HF1LDVSqNwDYCeezna2Cb1rVaQkCAlFDcqA1XHhvBaramwE19ew3cxLX7kwXI7uRXd+jy/WoqTxxZIE5SX0YeX89ji7npufxxa8/L93FHZ2QErhfIXx6xlHW9157PFCB7al/f17tXH9c34ZkExhGIAPGaaHA6BUiDk+Lqo8FJUVJVgbwKqVqAzs8KCJCzLFUf9E6rKr/OWxWIq5D8P98qlqfr1wIC5LWI7wkQaFIgAsSbq8ZmRoC0NyHeZTU2J8ohQOC8gAA57+LR8gJaJEBgMAEB0tiE+rCwsQlRTjMCXhvNTMXvQgTIbwpfECBAYFCBjYYlQDaC1SwBAgRGFxAgo8+w8REgQGAjAQGyEaxmRxIwFgIEzgkIkHMqHiNAgACBDwUEyIdEnkCAAAEC5wT2CJBz/XqMAAECBDoXECCdT6DyCRAgUEtAgNSS1y+BPQT0QWBDAQGyIa6mCRAgMLKAABl5do2NAAECGwoIkIu4fkiAAAEC7wkIkPdkPE6AAAECFwUEyEUePyRAoJaAftsXECDtz5EKCRAg0KSAAGlyWhRFgACB9gUESPtzdF+FK/b66+vy2cbg9TGw4pCy66ACAmTQiV0zrJ/L8vBjWf62MTgdA3lMrDmm7DumgAAZc16NigCBegLT9CxApplqAyVAgEBZAQFS1lNrBAgQmEZAgEwz1f0MVKUECPQhIED6mCdVEiBAoDkBAdLclCiIAAECtQRu61eA3Obl2QQIECBwFBAgRwh3BAgQIHCbgAC5zcuzCVwS8DMCUwkIkKmm22AJECBQTkCAlLPUEgECBKYSaCpAppI3WAIECHQuIEA6n0DlEyBAoJaAAKklr18CTQkohsDtAgLkdjN7ECBAgEAICJBAcCNAgACB2wUEyO1m5/bwGAECBKYTECDTTbkBEyBAoIyAACnjqBUCBGoJ6LeagACpRq9jAgQI9C0gQPqeP9UTIECgmoAAqUbfSsfqIECAwH0CAuQ+N3sRIEBgegEBMv0hAIAAgVoCvfcrQHqfQfUTIECgkoAAqQSvWwIECPQuIEB6n8GZ6zd2AgSqCgiQqvw6J0CAQL8CAqTfuVM5AQIEagkc+hUgBwZ/ESBAgMCtAgLkVjHPJ0CAAIGDgAA5MPiLwL4CeiMwgoAAGWEWjYEAAQIVBARIBXRdEiBAYASBPgNkBHljIECAQOcCAqTzCVQ+AQIEagkIkFry+iXQp4CqCfwWECC/KXxBgAABArcICJBbtDyXAAECBH4LCJDfFPt8oRcCBAiMIiBARpnJguP4tCzf4sD4YlsYLL8M8pgoeIhpahCBOEcMMhLDKCbwz/flycbg9TFQ7ACr1pCOSwsIkNKi2iNAgMAkAgJkkok2TAIECJQWECClRcdtz8gIECDwQkCAvODwDQECBAhcKyBArpXyPAIECNQSaLRfAdLoxCiLAAECrQsIkNZnSH0ECBBoVECANDoxyiopoC0CBLYQECBbqGqTAAECEwgIkAkm2RAJECCwhcA1AbJFv9okQIAAgc4FBEjnE6h8AgQI1BIQILXk9UvgGgHPIdCwgABpeHKURoAAgZYFBEjLs6M2AgQINCwweIA0LK80AgQIdC4gQBqbwL++Lp8XfwgQeCPgtfGGpPoDAqT6FCiAwJgCRjW+gAAZf46NkMAQAj+WxdX50tYfAdLWfCw/l+WhsZKUQ4AAgbMCAuQsS70HI0B+vcuqV4KeCbQq4M1VYzMjQBqbkCzHh4WpYCPwR+BfX5fHxZ/mBARIc1OyLHEV8tBgWUoiUFNgz9dEzXF21bcAaXC6IkA+uwppcGKUVEXA1UcV9qs6FSBXMe3/pB/L8vf+veqRQJMCrj6anJZlESCNTkyW9e+vfYZI1m4jUELAa6CE4nZtCJDtbFe3nEtZLt9XM2qgU4E89vM10Gn5U5QtQNqf5od8IbVfpgoJlBM4XnlYurqZdN8dBMi+3vf29nB8Qd27v/0IdCGQvzySx7orjy6m8+hetQAADT1JREFUy2cgfUzTsuQLKq5Efsbm9+F7mTR13iSQx3b+8kge6zft6MnVBFyBVKO/u+Nc0joESb5bu7sVO54T8NjOAnkM5xVHhEfkxvKwc/e6WykgQFYCVtz9Id+t5QsvtsfnW74ob90qjuNN17fWPsvz30BVfOBe89NxegqNPIYjOfz3PRXnck3XAmSNXjv75ju331u+KG/d2hnKstxa+yzPH2GOYgwPuQmNUBjgVjRABvCYdgj5jrKVwX9alqfFn9cC314/UOv7vIqo1bd+2xIQIG3NR7Vq4h1hvjOs1v/zjiNAmjlZPq/L1wQIvBQQIC89pv0uAqSZdeh/vi+uQJaXf/77ffngt++WPf8082Zjz0Hr662AAHlrMu0jlrGanfpmrsgsXzV7jFQpTIBUYW+z07gKaeadpWWsNo8RVRF4LiBAfmn4OwQiQCxjhUNrN8tXrc2Iek4CAuQk4f4gYBnrwNDSX5avWpoNtbwQECAvOHwTVyGWsRwG+wrorVsBAdLt1G1TeASIZaxtaO9q1fLVXWx22klAgOwE3VM3lrGamS3LV81MhULOCQiQcypdPVa+2LgKsYxVnlWLBIYTECDDTen6AUWAWMZaz7i6BctXqwk1sLGAANkYuNfmLWNVnznLV9Wn4OMCZn+GAJn9CHhn/HEVYhnrHRsPEyDwS0CA/HLw9yuBCBDLWK9M9vzW8tWe2vq6V0CA3Cs3wX6bL2PdYPhprv/i3fLVDceGp9YTECD17JvvOa5CLGM1P0sKJFBPQIDUs2++5wgQy1gVZsnyVQX0+bosMmIBUoRx3EYsY+0+t5avdifX4b0CAuReuUn2i6sQy1iTzLVhErhVQIDcKjbZ8yNALGOdmfOtHrJ8tZWsdrcQECBbqA7WpmWs3SbU8tVu1DoqISBASigO3kZchVjGGnyODY/APQJ1AuSeSu1TTSACxDLWDvqWr3ZA1kVRAQFSlHPcxixjbT63lq82J9ZBaQEBUlp00PbiKsQy1hhzaxQEigkIkGKUYzcUAWIZa8Mptny1Ia6mNxMQIJvRjtewZazN5tTy1Wa0Gt5SQIDcqDvz0+MqxDLWzAeAsRN4JSBAXoH49n2BCBDLWO/z3P0Ty1d309mxsoAAqTwBvXVvGav4jFm+uprUE1sTECCtzUjj9cRViGWsxudIeQT2EhAge0kP0k8EiGWsgnNp+aogpqZ2FxAgu5NX67BYx5axilFavipGqaEaAgKkhnrnfcZViGWszudQ+QRKCAiQEoqTtREBYhmrwJxbviqA2EsTg9YpQAad2K2HZRlrtbDlq9WEGqgtIEBqz0Cn/cdViGWsTudO2QRKCQiQUpKTtRMBsuMy1mXcf74vT0tnfyxfdTZhyj0rIEDOsnjwGgHLWNconX2O5auzLB7sTUCANDZjMSFfetlaovvP96Ubt5jfZq6Y8koo6unGrqVjbpZaLo0zjp1LP/azvQVyOaanbW+fS/1xu6Tz/s+4vW/jJ5cFBMhlHz8lQIAAgXcEBMg7MB4mUERAIwQGFhAgA0+uoREgQGBLAQGypa62CRAgMLBA4wEysLyhESBAoHMBAdL5BCqfAAECtQQESC15/RJoXEB5BD4SECAfCfk5AQIECJwVECBnWTxIgAABAh8JCJCPhO79uf0IECAwuIAAGXyCDY8AAQJbCQiQrWS1S4BALQH97iQgQHaC1g0BAgRGExAgo82o8RAgQGAnAQGyE3RP3aiVAAEC1wgIkGuUPIcAAQIE3ggIkDckHiBAgEAtgb76FSB9zZdqCRAg0IyAAGlmKhRCgACBvgQESF/zpdrLAn5KgMCOAgJkR2xdESBAYCQBATLSbBoLAQIEdhR4ESA79qsrAgQIEOhcQIB0PoHKJ0CAQC0BAVJLXr8EXgj4hkB/AgKkvzlTMQECBJoQECBNTIMiCBAg0J/AKAHSn7yKCRAg0LmAAOl8ApVPgACBWgICpJa8fgmMImAc0woIkGmn3sAJECCwTkCArPMrvvdfX5fPNgaOgfPHQPEXnAZXCQiQVXwldn7Zxo9l+dvGwDFw/hh4+WrxXW0BAVJ7BvRPgACBTgUESKcTp2wCBNYLaGGdgABZ52dvAgQITCuwOkD++b48Lf4QIECAQFcCJc7dqwOkKzHFlhXQGgECUwsIkKmn3+AJECBwv0CRAPm0LJaxFn8IECCwm8Cqjkqds4sEyKqR2JkAAQIEdhX4uSz/V6LDIgFSqpgSA9IGAQIECOwjUCRAohFLWPvMl14KCWiGAIH1AnHuX9+IFggQIECgH4E48Rd50x/trB90id8nXl+FFggQIEDgGoFS5+z7AuRMhaU+1T/TtIcIECBAoEGBYgHS4NiURIAAAQJvBb69fei+R4oFSFyBFCvqvqHYi8AUAgZJoBmBYgHSzIgUQoAAAQLvCvz3+/K4FPpTLEDyQ5m4CinyyX6hsWmGAAECBDYUKBYgG9ZYtGmNESBAYGKBoh81FA2QuAIpWtzEk2zoBAgQaF6gaIDkMlbzI1YgAQKVBHRbW6Dk5x85lqIBkg3GVYjPQRLCRoAAgbYEiq8QbREgxYtsaw5UQ4AAgf4E4mRf/M19tFkWIpexXIWUNT225o4AAQJ3C+S5+e6d39mxeIBkP/5791SwESBAoBmBTVaGNgmQaLT4pVIz06AQAgTmE+h8xKU/PD9xxLn+9GW5+7xUsoxVzlNLBAgQWCGwydVH1rNJgGTDESCbFZ3t2wgQIEDgY4E4yW+2IhRtf1zAPc9wFXKP2qj7GBcBApUEvuW5eKu+NwuQLNhVSCrYCBAgMKbApgGSyRchstnl05hTYlQECBAoIvAtPzwv0tI7jWwaINlnBIjPQhLCRoAAgcEENg8QVyGDHTGGQ4BADwKbX30kwuYBkp385/vyJe9tBLoTUDCBDgW2Xro6kewSIMfOLGUdIdwRIEBgQ4HdzrW7BUgmYnwe4gP1DY8aTRMgMLdAnmPzXLuXwsYB8nIYMbjdkvFlz74jQIDA+AJ7/z+EuwZIfqAeUyhEAsGNAAEChQV2+eD8ec27Bkh2nJdXcSViKSsxbAQ2FND0PAJ5Ts1z694j3j1AcoAxWFchCWEjQIBAAYFav+laJUByKSs69qu9BQ4cTRAgML1AtTfkcR6vg58hEj1XG3j0ffnmpwQIEGhfYPfPPZ6TVAuQLCLX7GI5y+chiWEjQIDAbQJVwyNLrRogWUCu3QmRlLARIHAUcPeBQJ4z8w34B0/b/MfVAyRHKERSwUaAAIGPBTI88pz58TO3f0YTAZLDbAUka7ERIECgVYGWzpXNBEhOVhTjN7MSYuVmdwIExhRo7RwZ9bQDnb+ZFQUJkXamRCUECDQikOfGPEc2Us6hjKjpcN/MXwkUHw59ynW+ZopSCAECBK4SKP+kPBfmOTHPjeVbX9dicwFyGk6u8yXc6Xv3BAgQmE0gz4F5Lmx13M0GSIId4fxjw8SwESAwlUDr4ZGT0XSAZIFx6fYY90IkECa4GSIBAr8Evh3fQP/6rtG/mw+QdBMiqWAjQGAGgTgpfzme85ofbtTafI2HAhM0Nh+uHzT8RYDAaAK5ZBUn5C/VPiy/AzTqvWOvirscL+ssaVWcA10TIFBc4LBk1VN4pEB3AZJFx5XI4XORTOz83kaAAIEeBfIcFifhbpasXhtH7a8f6uP7DBFXI33M1RxVGiWBmwW6vOp4PspuA+Q0iAyS2CLIF8taJxT3BAg0KxAnq6c8Z8WWKynN1nlNYd0HyGmQx8nIEMnt9LB7AgQINCGQwREn3C/HlZMmalpbRIxnbRNF9i/SSIZIbtFYhkhu8aUbAQIE6gk8D47ePiT/SG2oADkNNkMktxhc/seMguQE454Agd0ERg6OE2KcY09fjnefaZ9BElvMpc9IxpthIyoioJFiAnGieYrGvsWJ9bBUleeg+H7YW4xz2LG9GFiEyGNsn2LArkpeyPiGAIG1AhkceW7JzzfiPPM4enCcvGLMpy/nuM+JzQmOLeb8cFViiWuOqTdKAsUE4uTxlFucQPPfcHzK4MhzS7EOOmkoxt9JpRuUGSGSVyW5fYqv43i4J1A2KEyTBAg0JRAnh9+BESfNw/LUrKHxfGLC4vm3c38dIZJhktshUALntNyVVynf8iCaW8joCYwtkK/x3GKUh88x8hwQ54XDFcYpMGa80giPs7fwOfu4B0MgD5Q4eDJQDlseQPH9IVzyPvC+2BYGC4Nar4MS/eZr+bTlazy3+P7wOUaeA+JU4PaOQPi/8xMPfyiQB5dteWLAoOdj4MMXuie8KyBA3qXxAwIECBC4JCBALumM/jPjI0CAwAoBAbICz64ECBCYWUCAzDz7xk6AQC2BIfoVIENMo0EQIEBgfwEBsr+5HgkQIDCEgAAZYhrnG4QREyBQX0CA1J8DFRAgQKBLAQHS5bQpmgABArUE/vQrQP5Y+IoAAQIEbhAQIDdgeSoBAgQI/BEQIH8sfEVgDwF9EBhGQIAMM5UGQoAAgX0FBMi+3nojQIDAMALdBcgw8gZCgACBzgX+HwAA//9zyx96AAAABklEQVQDAJtKe01liJjNAAAAAElFTkSuQmCC // @match https://movie.douban.com/subject/* // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_setClipboard // @grant GM_getValue // @grant GM_setValue // @grant GM_openInTab // @connect bimzcy.github.io // @connect www.imdb.com // @connect query.wikidata.org // @connect www.rottentomatoes.com // @connect api.themoviedb.org // @connect www.themoviedb.org // @connect www.metacritic.com // @connect backend.metacritic.com // @connect metacritic.com // @connect letterboxd.com // @connect www.allocine.fr // @connect graphql.anilist.co // @connect www.omdbapi.com // @connect bgm.tv // @connect myanimelist.net // @connect neodb.social // @connect zduo.me // @connect wikidata.org // @connect api.frankfurter.dev // @connect api.graphql.imdb.com // @connect m.maoyan.com // @connect www.maoyan.com // @connect boxofficemojo.com // @connect api.ratetend.com // @connect www.ratetend.com // @connect api.tvmaze.com // @connect www.tvmaze.com // @connect mydramalist.com // @connect www.mydramalist.com // @connect www.commonsensemedia.org // @connect movie.mtime.com // @connect front-gateway.mtime.com // @connect film.mtime.com // @require https://lib.baomitu.com/jquery/3.6.0/jquery.min.js // @require https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js // ==/UserScript== (function() { 'use strict'; // Base64 图标 const AL_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAD5UExURRkhLRkhLRkhLRkhLUxpcRkhLRkhLRkhLRkhLRkhLRkhLRkhLRkhLRkhLf///v///xgfLACq/wCs/xQdKgN4sfv7+wCo/A1Pc6irrwR1rvf3+GZrdKCjp6WorRkfKv39/QVzqmRpcUpQWuHi4zpBSygvO5WZnjE3Qtzd3xAYJfHy8uXm5yW4/+r3/hFAXX6DiQR9uQZupHd7grCzt25zelNYYsvN0Pb8/2XM/8zv/wmx/xkfKTy//3zU/yIqNQR5s4qNkxUwQ8DCxrq8vyxAUF1iat7z/mGUsAdikqTU7luPrtLT1U7G/4zY/tHT1avj/hONyr/p/rXm/lS/nxsAAAANdFJOU/ua3pYAfRAOd9nd4J6x3JfpAAABaUlEQVQ4y4WTh1LCQBCGDw0B1OQud4IhCakUKaJIb/be9f0fxivRgeESvskwyew3+yfLHlBy+QLQpIBCXlVAbjehzJWMCvIpdWpkQUFLZQ+AdGGljgQuvdxV479erTuOU7978v1eF0kEcgopxccSxtiXCRc3UKc8lwwDH0oiSNjiwkMnSbjidd2byAVUGwlB/8RSgQxpgmdR4aQj71CHOmxVmDGRCaj2SoWP8Jjm/GCJQO4tKjiaCXmGJMKhFSto2kWasdwUUIP2hu2wEbap+D3bEIjN3s6Kooh/x2IzwuRDoP8FH8WyPJ+7DBQLqBrFUxJMv44E10gIZMDezSsyPHo3XpQ4Ri/uAPq0AewHtm0Ht6zXu8HBZ0JA1TYb47BJCGkGrNl0tiaIVRnVUPzBEI7fDMy4jCPOzUrFHMRbxB9eygy/i/4GxVjdXU38uOtrnbD2Ww7Ozvajp2bSDu+BChQ1u5Ok7GdV5Reeuka5jCikYgAAAFd6VFh0UmF3IHByb2ZpbGUgdHlwZSBpcHRjAAB4nOPyDAhxVigoyk/LzEnlUgADIwsuYwsTIxNLkxQDEyBEgDTDZAMjs1Qgy9jUyMTMxBzEB8uASKBKLgDqFxF08kI1lQAAAABJRU5ErkJggg==" const LBX_ICON = "data:image/vnd.microsoft.icon;base64,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Bv9elyT/ZVdD/2ZVRP9tWkT/upJB/+u2QP/0vED/9LxA/9+sQf+Wd0P/ZlVE/2ZVRP9mVUT/aFZER2dWRJVmVUT/ZlVE/y1tq/8AgP//AID//wCA//8AgP//AID//wCA//8Meuf/XFpS/1m9Ef9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9ZvRH/cV9D/+KvQP/0vED/9LxA//S8QP/0vED/9LxA//S8QP+0jkL/ZlVE/2ZVRP9nVkSVZ1VEv2ZVRP9KYXf/AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//9ap8n/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP/SxWv/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP+NcUP/ZlVE/2dVRL9mVkTZZlVE/x5zxv8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AoD//+32//9l3Dj/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/eeAq//768f/0vEH/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA/8mdQf9mVUT/ZlZE2WdVRPNmVUT/Cnzs/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8gj////////3rXhv9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP+r42H///////XEV//0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/57JA/2ZVRP9mVUTyZ1VE82ZVRP8KfOz/AID//wCA//8AgP//AID//wCA//8AgP//AID//yGQ////////eteG/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/6vjYf//////9cRX//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/nskD/ZlVE/2dVRPNmVkTZZlVE/x5zxv8AgP//AID//wCA//8AgP//AID//wCA//8AgP//A4H//+32//9l3Dj/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/eeEq//768f/0vEH/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA/8mdQf9mVUT/ZlZE2WdVRL9mVUT/SmF3/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//W6fK/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1Tg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RP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dVReloVkU7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoVkZiZlVF+WZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVF+WhWRmIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKpVVQNmVkSOZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlZEjqpVVQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKpVVQNmVUWxZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUWxqlVVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmVkSOZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZWRI4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoVkZiZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/aFZGYgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoVkU7ZlVF+WZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRfloVkU7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmVUQeZ1VF6WZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/Z1VF6WZVRB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8BZ1ZFxGZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9nVkXE////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ1dEYWZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dXRGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcGBQEGZVRepmVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUXqcGBQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhWRoBmVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2hWRoAAAAAAAAAAAAAAAAAAAAAAAAAAAHZiTg1nVkXuZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9nVkXudmJODQAAAAAAAAAAAAAAAAAAAABmVkVzZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZWRXMAAAAAAAAAAAAAAAAAAAAAZ1VE1WZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9nVUTVAAAAAAAAAAAAAAAAaVVGM2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2RWRv9SXmj/RmJ9/0Blif9IYnr/VVxi/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2VfPv9heDP/YIYs/2CGLP9heDP/ZV8+/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/31mRP+Pc0P/m3xC/5J1Qv+CaUP/Z1dE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2lVRjMAAAAAAAAAAGdVRY1mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/V1xe/ydvt/8HffH/AID//wCA//8AgP//AID//wCA//8Me+j/L2yn/15ZUf9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUP/YIQt/1m+EP9V3wD/VOAA/1TgAP9U4AD/VOAA/1XfAP9ZvhD/YIQt/2ZVQ/9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9wXUT/soxC/+OwQf/0vED/9LxA//S8QP/0vED/9LxA/+m0Qf++lEL/emRE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9nVUWNAAAAAAAAAABmVUTSZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9kVkb/MGyn/wJ/+/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8GfvT/P2WL/2ZVRP9mVUT/ZlVE/2ZVRP9kZzr/WMMO/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9Yww7/ZGc6/2ZVRP9mVUT/ZlVE/2ZVRP+cfEP/7LZB//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//K6QP+yjEL/Z1dE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE0gAAAABtVUkVZlVE/mZVRP9mVUT/ZlVE/2ZVRP9iV0r/HHTK/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8tbav/ZlVE/2ZVRP9idDT/VdYF/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1XWBf9idDT/ZlVE/2ZVRP+0jkL/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA/8yfQf9rWUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP5tVUkVaFZHU2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/I3G+/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//zdpmf9kZzr/VdYF/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VdYF/2RnOv+nhUL/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/w5lB/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/aFZHU2dVRX5mVUT/ZlVE/2ZVRP9mVUT/PmaM/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8Af/3/Xb9W/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP+IyTX/87tA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP+dfUL/ZlVE/2ZVRP9mVUT/ZlVE/2dVRX5mVUSlZlVE/2ZVRP9mVUT/YldL/wp76/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//RKH//7Pd6f9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/7eu6//bOc//0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/5rFA/2xZRP9mVUT/ZlVE/2ZVRP9mVUSlZ1VFy2ZVRP9mVUT/ZlVE/0Jlhv8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//7jb///9/v//X9dD/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/gN4q//7+/P/77Mr/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP+ZekP/ZlVE/2ZVRP9mVUT/Z1VFy2dWRd9mVUT/ZlVE/2ZVRP8icb//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wuF/////////////4rVsv9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/8jkgf////////////S+SP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/xJlB/2ZVRP9mVUT/ZlVE/2dWRd9nVUTsZlVE/2ZVRP9mVUT/D3nj/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8vl/////////////+h2Nr/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP/j6Kb////////////2yGP/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA/9+sQf9mVUT/ZlVE/2ZVRP9nVUTsZlVF+WZVRP9mVUT/ZlVE/wR+9v8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//VKn/////////////v+Pt/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/8e/G////////////99J+//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/tuED/ZlVE/2ZVRP9mVUT/ZlVF+WZVRflmVUT/ZlVE/2ZVRP8Efvb/AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//1Sp/////////////7/j7f9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA//Hvxv////////////fSfv/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/7bhA/2ZVRP9mVUT/ZlVE/2ZVRflnVUTsZlVE/2ZVRP9mVUT/D3nj/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8wl/////////////+h2Nr/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP/j6Kj////////////2yGP/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA/9+sQf9mVUT/ZlVE/2ZVRP9nVUTsZ1ZF32ZVRP9mVUT/ZlVE/yJxv/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//DYb/////////////itWy/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/yeSC////////////9L5I//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/EmUH/ZlVE/2ZVRP9mVUT/Z1ZF32dVRctmVUT/ZlVE/2ZVRP9CZYb/AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//+42////f7//1/XQ/9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/3/eKf/+/v3/++zK//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/mXpD/2ZVRP9mVUT/ZlVE/2dVRctmVUSlZlVE/2ZVRP9mVUT/YldL/wp76/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//SKP//7Pd6f9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/7uy9//bOc//0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/5rFA/2xZRP9mVUT/ZlVE/2ZVRP9mVUSlZ1VFfmZVRP9mVUT/ZlVE/2ZVRP8+Zoz/AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wF//f9fwFj/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/4rKOP/zu0D/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA/519Qv9mVUT/ZlVE/2ZVRP9mVUT/Z1VFfmhWR1NmVUT/ZlVE/2ZVRP9mVUT/ZlVE/yNxvv8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//83aZn/ZGc6/1XWBf9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1XWBf9kZzr/p4VC//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA/8OZQf9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2hWR1NtVUkVZlVE/mZVRP9mVUT/ZlVE/2ZVRP9iV0r/HHTK/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wCA//8tbav/ZlVE/2ZVRP9idDT/VdYF/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1XWBf9idDT/ZlVE/2ZVRP+0jkL/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA/8yfQf9rWUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP5tVUkVAAAAAGZVRNJmVUT/ZlVE/2ZVRP9mVUT/ZlVE/2RWRv8wbKf/An/7/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AID//wZ+9P8/ZYv/ZlVE/2ZVRP9mVUT/ZlVE/2RnOv9Yww7/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1TgAP9U4AD/VOAA/1jDDv9kZzr/ZlVE/2ZVRP9mVUT/ZlVE/5x8Q//stkH/9LxA//S8QP/0vED/9LxA//S8QP/0vED/9LxA//S8QP/0vED/8rpA/7KMQv9nV0T/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUTSAAAAAAAAAABnVUWNZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/1dcXv8nb7f/B33x/wCA//8AgP//AID//wCA//8AgP//DHvo/zBsp/9eWVH/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVD/2CELf9ZvhD/Vd8A/1TgAP9U4AD/VOAA/1TgAP9V3wD/Wb4Q/2CELf9mVUP/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/cF1E/7KMQv/jsEH/9LxA//S8QP/0vED/9LxA//S8QP/ptEH/vpRC/3pkRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/Z1VFjQAAAAAAAAAAaVVGM2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2RWRv9SXmj/RmJ9/0Blif9IYXn/VVxi/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2VfPv9heDP/YIYs/2CGLP9heDP/ZV8+/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/31mRP+OckP/m3xC/5J1Qv+CaUP/Z1dE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2lVRjMAAAAAAAAAAAAAAABnVUTVZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dVRNUAAAAAAAAAAAAAAAAAAAAAZlZFc2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVkVzAAAAAAAAAAAAAAAAAAAAAHZiTg1nVkXuZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9nVkXudmJODQAAAAAAAAAAAAAAAAAAAAAAAAAAaFZGgGZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/aFZGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBgUBBmVUXqZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVF6nBgUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ1dEYWZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dXRGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wFnVkXEZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dWRcT///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZlVEHmdVRelmVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dVRelmVUQeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoVkU7ZlVF+WZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRfloVkU7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhWRmJmVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9oVkZiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZlZEjmZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVkSOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKpVVQNmVUWxZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUWxqlVVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqlVVA2ZWRI5mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVkSOqlVVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaFZGYmZVRflmVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRfloVkZiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABoVkU7Z1VF6WZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dVReloVkU7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGZVRB5nVkXEZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dWRcRmVUQeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AWdXRGFmVUXqZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVF6mdXRGH///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcGBQEGhWRoBnVkXuZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9nVkXuaFZGgHBgUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmJODWZWRXNnVUTVZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2dVRNVmVkVzdmJODQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGlVRjNnVUWNZlVE0mZVRP5mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP9mVUT/ZlVE/2ZVRP5mVUTSZ1VFjWlVRjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtVUkVaFZHU2dVRX5mVUSlZ1VFy2dWRd9nVUTsZlVF+WZVRflnVUTsZ1ZF32dVRctmVUSlZ1VFfmhWR1NtVUkVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAD///////gAAB//////wAAAA/////8AAAAA/////AAAAAA////4AAAAAB////AAAAAAD///4AAAAAAH//+AAAAAAAH//wAAAAAAAP//AAAAAAAA//4AAAAAAAB//AAAAAAAAD/4AAAAAAAAH/AAAAAAAAAP8AAAAAAAAA/gAAAAAAAAB+AAAAAAAAAHwAAAAAAAAAPAAAAAAAAAA8AAAAAAAAADgAAAAAAAAAGAAAAAAAAAAYAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAYAAAAAAAAABgAAAAAAAAAHAAAAAAAAAA8AAAAAAAAADwAAAAAAAAAPgAAAAAAAAB+AAAAAAAAAH8AAAAAAAAA/wAAAAAAAAD/gAAAAAAAAf/AAAAAAAAD/+AAAAAAAAf/8AAAAAAAD//wAAAAAAAP//gAAAAAAB///gAAAAAAf///AAAAAAD///+AAAAAAf///8AAAAAD////8AAAAA/////8AAAAP/////+AAAH///////AAD///8=" const ALC_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHYAAAB2BAMAAADviXoiAAAAGFBMVEUAAAAmJib/////ywBcUzPIoQmUehKRkZFw3PDCAAAAAXRSTlMAQObYZgAAA2BJREFUWMPdmU1P20AQQKv+AzeOe3WjSD1HG+fuptBz5JS7lY87qBJ/vxCyed6ZHS94b8wBiOTHzL7xLvbw5VPF18Vb1B8mF8OYQhIfqFZHPRUFTqNTYdA0nEaBk+hkOIoQ70Wf2+I1ymcBpyv+VxB/gqpTaX8WYTwlE8uk0dSJih8LHd/HqxaoBY+lXRbx+DWSGE1hlIc+FGanVWjnVtcfzcTGYu+dcxuxZIOVFZ/cSzSizUbJraz3Eq3/HC866njr3qIXru20xOzKrgojMaxq7fzKrmlyhCWtYpFFYp0WybDIQjWJYektrpBFj2Ep+VaYv/Tg2R2/j6KH7A9/K3XejfOxhv0Gq0u+e7mW5SIrUjTsdddQ48HdoiAES3OrDjl3jujlPob1JVfOx/n36fL94dxRyKBoUTIrJI7X/GtVNOz1xigFuvf2NvLArXWHOkegt0MWXQqW69USO+6vVi8YtmXXqa7OAlklLKqELARtDVmokrKo02lZsNzMsZIrPiBLsELWipIpAjbQzHXiPrTuLDQrWTevVKFEozm4ozeDDglZmkUWie57r6AxWY65Q7Dczh19Ja1o0rC9yOLaSm9hGuzZpT6T5S26Etu/lu0l1YYF6PPOYIvhpWJnJNmOEktIZJkssnbUj6xRFj+9Or52abaC3QbsOsGyyFaxzTiLLFgiwdJUfkLWOIsslCMrzVYWu06z5Y0tTwG7gY3tBWTxdEbE9gJ7EFksnmjVIavYGdeFt9YOVp85XB9l16PnFbJ6WCVLn7EE9YVsEz9jH6WsFayQxdlOg4kt9altaP89Amhi7EqyusEVsugvsmgvf7sJGgKLrAVsRPTBJ4ZFFpqlaM67po1vYf2sgiwM/T2fXhd5+YponpFMWTyf8fkoVBmy0BMsAlXmgjuqvN3iD/KJAXYZyvJxM78Xz8Bm0TO5dea9eDKzX1MqsWXtZ37dpZI7WAQdghVFd6gixDuOVfQB1ijZfqebGTU/wZrvklXMFe+S9jssspo+Nqio7XdnZG3aaNrafGdH1t6Yj1izAmQ1RyCRNjGjmDeiXmYU6dmIPQ6yZzJ2MJNJz4KM4VnODCpj9pUzc8ub9eXPGPNnm/kzVWA78mfI+bPr/Jl5/qwe2EKnwnXe/0Sm0Rn/A/pM8R8w2HBWwA4YRgAAAABJRU5ErkJggg==" // 样式注入 GM_addStyle(` #content h1 { margin-bottom: 0px !important; padding-bottom: 0px !important; line-height: 1.1 !important; } #dme-header-ratings { display: inline-flex !important; flex-wrap: wrap; width: 100%; align-items: center; margin: 4px 0 10px 0 !important; padding: 0 !important; gap: 8px; user-select: none; clear: both; } .drdm-capsule { display: inline-flex; align-items: center; border-radius: 4px; font-size: 13px; height: 24px; overflow: hidden; box-shadow: 0 1px 2px rgba(0,0,0,0.1); font-family: Arial, sans-serif; } .drdm-capsule a { text-decoration: none !important; display: flex; align-items: center; height: 100%; } /* 烂西红柿胶囊 */ .drdm-capsule.rt-cap { background: #fff; border: 1px solid #ddd; } .drdm-rt-chip { display: flex; align-items: center; padding: 0 6px; height: 100%; font-weight: bold; color: #fff; } .drdm-rt-chip.critics { background: #fa320a; } .drdm-rt-chip.audience { background: #ffb300; color: #2c2c2c; } /* Metacritic 双拼胶囊样式 */ .mc-cap { background: #fff; border: 1px solid #ddd; display: inline-flex !important; align-items: stretch; height: 24px; margin-right: 8px; border-radius: 4px; overflow: hidden; } .drdm-mc-chip { padding: 0 7px; display: flex; align-items: center; font-weight: bold; font-size: 13px; height: 100%; } .drdm-mc-chip.users { background: #fccb30; color: #000; border-left: 1px solid #ddd; } /* 统一黄色系胶囊 (Meta, Letterboxd, Allocine) */ .drdm-capsule.yellow-cap { background: #ffcc33; border: 1px solid #d9aa00; color: #111; padding: 0 7px; font-weight: bold; } .drdm-capsule img { height: 14px; margin-right: 5px; } .view-original-btn { display: block !important; margin: 12px auto 0 !important; padding: 4px 0 !important; border: 1px solid #556783 !important; color: #556783 !important; border-radius: 2px !important; font-size: 13px !important; text-decoration: none !important; text-align: center !important; width: 120px !important; background: #f0f3f5 !important; } `); const movieId = window.location.pathname.split('/')[2]; const orangeColor = "#f0ad4e"; const tmdbAuth = "Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMzc1ZGIzOTYwYWVhMWI1OTA1NWMwZmM3ZDcwYjYwZiIsInN1YiI6IjYwYmNhZTk0NGE0YmY2MDA1OWJhNWE1ZSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.DU51juQWlAIIfZ2lK99b3zi-c5vgc4jAwVz5h2WjOP8"; // 核心:强制排序插入逻辑 const CAPSULE_ORDER = ['header-rt-score', 'header-alc-score', 'header-mtc-score', 'header-anilist-score', 'header-lbx-score']; function renderHeaderCapsule(id, html) { if (document.getElementById(id)) return; const container = getHeaderContainer(); if (!container) return; const tempWrap = document.createElement('div'); tempWrap.innerHTML = html; const newEl = tempWrap.firstElementChild; newEl.id = id; // 查找位置:遍历顺序表,寻找当前 ID 之后的已存在元素 const myIndex = CAPSULE_ORDER.indexOf(id); let inserted = false; for (let i = myIndex + 1; i < CAPSULE_ORDER.length; i++) { const afterEl = document.getElementById(CAPSULE_ORDER[i]); if (afterEl) { container.insertBefore(newEl, afterEl); inserted = true; break; } } if (!inserted) container.appendChild(newEl); } function getHeaderContainer() { let container = document.getElementById('drdm-header-scores'); if (container) return container; container = document.createElement('div'); container.id = 'drdm-header-scores'; // --- 核心样式调整 --- // gap: 10px -> 统一所有胶囊之间的水平间距 // margin-top: 12px -> 调大胶囊与影视标题之间的距离 // margin-left: 0px -> 确保与标题左端对齐(如果还觉得不齐,可尝试 -1px) container.setAttribute('style', ` display: flex !important; flex-wrap: wrap; gap: 10px; margin-top: 12px; margin-bottom: 10px; align-items: center; clear: both; margin-left: 0px; `); // 插入在标题(h1)之后 const titleHeader = document.querySelector('#content h1'); if (titleHeader) { titleHeader.after(container); return container; } return null; } // --- 1. 排行榜终极修复:适配动画页面 rank-label 并统一合并 --- function initRankings() { const titleH1 = document.querySelector('#content h1'); if (!titleH1) { setTimeout(initRankings, 100); return; } // 创建唯一的 Flex 容器 let container = document.getElementById('unified-rank-wrapper'); if (!container) { container = document.createElement('div'); container.id = 'unified-rank-wrapper'; // 关键:margin-top 设为 10px 确保和标题有间距,底部 12px container.style.cssText = "display: flex !important; flex-wrap: wrap !important; gap: 8px !important; margin: 10px 0 12px 0 !important; padding: 0 !important; align-items: center !important; clear: both !important; width: 100% !important;"; // 确保容器在标题上方 titleH1.parentNode.insertBefore(container, titleH1); } const renderBadge = (no, name, url, isNative = false) => { const badgeId = isNative ? 'native-sync-badge' : `rank-${name}`; if (document.getElementById(badgeId)) return; const html = ` ${no} ${name} `; container.insertAdjacentHTML('beforeend', html); }; const syncNativeRank = () => { // 增加对动画页面 .rank-label 的识别 const nativeSelectors = '.top250, .top-list-rank, .rank-banner, .rank-label, .billboard'; document.querySelectorAll(nativeSelectors).forEach(el => { if (el.id === 'unified-rank-wrapper' || el.closest('#unified-rank-wrapper')) return; // 尝试多种方式提取排名 (No.XX) let noText = "No."; const noEl = el.querySelector('.rank-label-no, .top250-no, .rank, [class*="no"]'); if (noEl) { noText = noEl.innerText.trim(); } else { const match = el.innerText.match(/No\.?\s?\d+/i); if (match) noText = match[0].replace(/\s/g, ''); } // 提取榜单名称 let titleText = "豆瓣高分榜"; const linkEl = el.querySelector('.rank-label-link a, .top250-link, a'); if (linkEl) { titleText = linkEl.innerText.trim(); } else { titleText = el.innerText.replace(noText, '').replace(/[\s\(\)()]/g, '').trim(); } if (titleText.length > 15) titleText = "豆瓣高分榜"; const url = el.querySelector('a')?.href || window.location.href; renderBadge(noText, titleText, url, true); el.style.display = 'none !important'; // 隐藏原标签 el.remove(); // 彻底移除防止占位 }); }; // 立即执行 + 监听异步加载 syncNativeRank(); const obs = new MutationObserver(syncNativeRank); obs.observe(document.body, { childList: true, subtree: true }); // 获取 BGM / MAL 等第三方榜单 const movieId = (window.location.pathname.match(/subject\/(\d+)/) || [])[1]; GM_xmlhttpRequest({ method: 'GET', url: 'https://bimzcy.github.io/rank4douban/data.json', onload: function(res) { if (res.status === 200) { try { const data = JSON.parse(res.responseText); for (const k in data) { if (k === 'top250' || data[k].short_title.includes("Top250")) continue; if (data[k].list[movieId]) { renderBadge((data[k].prefix || 'No.') + data[k].list[movieId], data[k].short_title, data[k].href); } } } catch(e){} } } }); } // 判定是否为动画/动漫页面 function isAnime() { var genres = document.querySelectorAll('span[property="v:genre"]'); for (var i = 0; i < genres.length; i++) { if (genres[i].textContent.includes('动画')) return true; } // 兜底逻辑:如果在标签(Tags)里发现“动画”或“动漫” var tags = document.querySelector('#db-tags-section'); if (tags && (tags.textContent.includes('动画') || tags.textContent.includes('动漫'))) return true; return false; } // --- 影视名称(基于 Box Office Mojo 页面高效解析,避免额外请求 IMDb) --- function addMediaTitle() { // 防止重复添加 if ($('#info').find('span.pl:contains("影视名称")').length) return; var year = ''; try { year = $('span.year').text().match(/\d+/)[0]; } catch (e) {} var ch_name = $('h1').find('span:first').text().split(' ')[0]; // 清洗规则 function formatName(str) { return str.replace(/\s+/g, ' ') .replace(/ /g, '.') .replace(/:\./, '.') .replace('-.', '-') .replace('..', '.') .replace('.-', '-') .replace(/\.+$/, ''); // ★ 确保末尾没有 . } function appendName(en_name) { var raw = en_name ? `${ch_name} ${en_name} ${year}` : `${ch_name} ${year}`; var name = formatName(raw); var html = `影视名称: ${name}
`; $('#info').append(html); } // 兜底逻辑:无 IMDb 时从“又名”中提取英文名 function fallbackAkaName() { var en_name = null; try { var akaNode = $('#info span.pl:contains("又名")')[0]; if (akaNode && akaNode.nextSibling) { akaNode.nextSibling.textContent.trim().split('/').forEach(function (e) { e = e.trim(); if (e && e.match(/^[a-zA-Z0-9 '-:]*$/)) en_name = e; }); } } catch (err) {} appendName(en_name); } var imdbMatch = $('#info').html().match(/tt\d+/i); if (!imdbMatch) { fallbackAkaName(); return; } // 改为请求 Box Office Mojo 页面来获取影片英文标题 GM_xmlhttpRequest({ method: 'GET', url: 'https://www.boxofficemojo.com/title/' + imdbMatch[0] + '/', timeout: 15000, headers: { 'Accept-Language': 'en-US,en;q=0.9', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }, onload: function (res) { try { var doc = new DOMParser().parseFromString(res.responseText, 'text/html'); // Box Office Mojo 页面标题通常形如: "Movie Title - Box Office Mojo" var pageTitle = doc.querySelector('title')?.textContent || ''; var en_name = pageTitle.split('-')[0].trim(); if (!en_name || en_name.toLowerCase().includes('box office mojo')) { // 备用选择:尝试抓取 Mojo 页面上的大标题 en_name = doc.querySelector('h1.a-size-extra-large, h1[class*="a-size-extra-large"]')?.textContent?.trim() || ''; } // 剧集:拼接季号 Sxx if ($('span.pl:contains("季数")').length) { var number = $('#season option:selected').text().trim(); if (!number) { var sn = $('span.pl:contains("季数")')[0]; if (sn && sn.nextSibling) number = sn.nextSibling.textContent.trim(); } if (number) { if (number.length < 2) number = '0' + number; en_name = en_name + ' S' + number; } } appendName(en_name || null); } catch (err) { console.warn('影视名称生成失败:', err); fallbackAkaName(); } }, onerror: fallbackAkaName, ontimeout: fallbackAkaName }); } // --- 2. 核心控制器 --- async function initMain() { const movieId = location.href.match(/subject\/(\d+)/)?.[1]; const infoDiv = document.querySelector('#info'); const ratingWrap = document.querySelector('.rating_wrap.clearbox') || document.querySelector('.rating_logo')?.parentNode; if (!infoDiv || !ratingWrap) { setTimeout(initMain, 100); return; } // 影视名称 addMediaTitle(); let sideArea = document.getElementById("custom-side-area") || (()=>{ const div = document.createElement('div'); div.id = "custom-side-area"; ratingWrap.appendChild(div); return div; })(); // 侧边栏 sideArea.innerHTML = `
`; const imdbMatch = infoDiv.innerText.match(/IMDb:\s*(tt\d+)/) || infoDiv.innerText.match(/tt\d+/); const imdbId = imdbMatch ? (imdbMatch[1] || imdbMatch[0]) : null; // --- 修复后的 IMDb 扩展评分加载逻辑 --- if (imdbId) { // 使用统一的 Wikidata 桥梁函数 getExtraIdsFromWikidata(imdbId, function(ids) { // 这里的 data.Title 来自 OMDb 请求的结果 var movieTitle = (typeof data !== 'undefined' && data.Title) ? data.Title : document.title.split('(豆瓣)')[0].trim(); // 1. 加载 Allocine if (ids.allocineId) { fetchAllocineDualScores(ids.allocineId); } // 2. 加载 Metacritic // 注意:即便 Wikidata 没查到 mcId,函数内部也有标题兜底逻辑 fetchMetacriticDualScores(ids.mcId, movieTitle); // 3. 渲染大中华差异对比(新功能) if (ids.claims) { renderKanjiZoneComparison(ids.labels); renderBoxOfficeModule(ids.claims, imdbId).catch(error => { console.warn('电影收支模块渲染失败:', error); }); renderRatingModule(ids.claims); } }); } if (imdbId) { processOMDb(imdbId); processRottenTomatoes(imdbId); processTMDB(imdbId); processNeoDB(movieId); processMyDramaList(); processCommonSenseMedia(); processLetterboxd(imdbId); // === 动漫专属逻辑开始 === if (isAnime()) { // AniList 通常也是动漫专用,建议也放在这里 processAniList(imdbId); // 获取当前豆瓣页面的电影/动画标题,用于搜索 const titleHeader = document.querySelector('h1 [property="v:itemregulated"]') || document.querySelector('h1 span'); const title = titleHeader ? titleHeader.innerText.replace(window.location.pathname.split('/')[2], '').trim() : ''; if (title) { processBangumi(title); processMAL(title); } } // === 动漫专属逻辑结束 === } } // --- 3. 各平台逻辑 --- function processRottenTomatoes(imdbId) { const sparql = `SELECT * WHERE {?s wdt:P345 "${imdbId}". OPTIONAL { ?s wdt:P1258 ?RTID. }}`; GM_xmlhttpRequest({ method: "GET", url: `https://query.wikidata.org/sparql?format=json&query=${encodeURIComponent(sparql)}`, onload: res => { try { const rtId = JSON.parse(res.responseText).results.bindings[0]?.RTID?.value; if (!rtId) return; const rtUrl = `https://www.rottentomatoes.com/${rtId}`; GM_xmlhttpRequest({ method: "GET", url: rtUrl, onload: res => { const doc = new DOMParser().parseFromString(res.responseText, "text/html"); const jsonEl = doc.getElementById("media-scorecard-json"); if (jsonEl) { const json = JSON.parse(jsonEl.textContent); let tScore = json.criticsScore?.score; let aScore = json.audienceScore?.score; if (tScore || aScore) { let html = `
`; if (tScore) html += `🍅 ${tScore}%`; if (aScore) html += `🍿 ${aScore}%`; html += `
`; renderHeaderCapsule('header-rt-score', html); } } } }); } catch(e) {} } }); } /* --- Metacritic 修复版核心逻辑 --- */ // 2. 抓取与解析 function fetchMetacriticDualScores(mcId, title) { let path = mcId || ("movie/" + title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '')); const url = "https://www.metacritic.com/" + path; GM_xmlhttpRequest({ method: "GET", url: url, headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0" }, onload: function(resp) { if (resp.status !== 200) return; const parser = new DOMParser(); const doc = parser.parseFromString(resp.responseText, "text/html"); // 使用最新的选择器 const criticEl = doc.querySelector('div[data-testid="global-score-wrapper"]:has(a[href*="critic-reviews"]) span[data-testid="global-score-value"]'); const userEl = doc.querySelector('div[data-testid="global-score-wrapper"]:has(a[href*="user-reviews"]) span[data-testid="global-score-value"]'); const criticScore = criticEl ? criticEl.textContent.trim() : "N/A"; const userScore = userEl ? userEl.textContent.trim() : "N/A"; if (criticScore !== "N/A" || userScore !== "N/A") { renderMetacriticDoubleCapsule(path, criticScore, userScore); } } }); } // 3. 渲染 function renderMetacriticDoubleCapsule(path, critic, user) { // 1. 定义 Metacritic M 图标的 Base64 const mcIconBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACABAMAAAAxEHz4AAAAElBMVEUAAAAzMzP/zDT+/v5oX0elmG641eaPAAAAAXRSTlMAQObYZgAAA3ZJREFUaN69mVFym0AQBVO6ARL8WxQ5gGulAyzGBwDL979K4tjmie2dmVKo8nxZpKbV83YFBH65dej/lv3PYbPqf9tVTw/29yggwq9nPfL1uwi9Xfv6GUTcz4r7owrzD2tHP2KIB3j/qMVQCPtvU/NZ7bSAEA9wy81dCaEhfIHcFDVCwRP43bBeQ0LRj+qCIQ7oB8FXYD8JnsKB+bFGRwH9PuHJFBjQNE3T+ndrKpgBtG8ppeuqdSwUIDCX/emz1uOLC6BASgWhq89gJfiS1spFjk81gQEDqC7KEYBYQENIgQAuYbqvq61wMARO6qYCAVyCtwSF+4XABGdjAihoBn+CLqW6wkiAImQEVGiLGbSLsYiGwlIFNMzQUjhqBq4BM6RCWwOcLcC1oqAQBMgGIG9muW7WgRHwl/SsNO4UjgQMBiDrTykoBC+C9k75VCoQkBvU/Vlgq6AQBCguhB/yawRQ2ISAXaDQBIBCVwIG7GEBoLBNkRl2CQAqlIC5NoBCpMLyDdAiUEDLSIWxAJg/wlxX0DIIwGuBZqBCJ4BWEechKOhguwUMmKCqoGMCYBuk5Cno0BZwRgSGgo4QwEWkwnpAG0H7iBlSQZ8dgKugj+MGAEtLQZ8CwPX1zVLIDuA0fwEu64aAwqVxACl9AbSgUMh1wLff5aSzQAcFFQDrIv0Tn7GrcwRQft8TQCEGpAIAhQBwAgAKNmCWgABQ8AEnABwF/Rb0a3wBAAo+oEuqOVLg+QDXo1ABpzTeBEhBWBVOqhuFeaOgg6oWp3VPQcd0GBcWR4ECvDJlV4ECBIQKMzYiLu+uwtXYiNoIngIEeIMxNJ4CBLSKulF1FSDQCaAUHYVSoDkCMLsKOB8tAAyNo6BihrrTtBVYHQF94yk4ESiERxTGCmB4RKEXADNAIYhAgOwpcAICzoECJzD+8x4rdABoHajgTsAHGFSIJ5BCU1F4NnYRANb9asNa+Binp4IEGKENmKUQCvTmkzApxAJSYAq2gABU6LMU/CXow+eRbVWg7SWAGbAdKwKjBKDAXwT7OwhQYTBOxXikCgUSuAICsHrGwH5MAAUQECAFqEAC+32F/sb85M8BqND/LpZgwjsSS0ESGV8vAVdBFrfpo3l6f+g1T1z7X1TtJOx+WRdV1B9X1B+XG+A+wk+9NiaB+nGh/Wde3hMSN/8BSXUWJsXAq8kAAAAASUVORK5CYII=" // 2. 核心颜色逻辑 let bgColor = "#ffcc33"; // 默认黄色 (40-60) let textColor = "#000"; // 默认黑色 const score = parseInt(critic); if (!isNaN(score)) { if (score <= 39) { bgColor = "#ff0000"; // 红色 textColor = "#fff"; // 白色 } else if (score >= 61) { bgColor = "#66cc33"; // 绿色 textColor = "#fff"; // 白色 } } // 3. 构造 HTML const html = '
' + '' + // 前半个胶囊 (Expert Score) '
' + '' + '' + critic + '' + '
' + // 后半个胶囊 (User Score) '
' + '👤' + '' + user + '' + '
' + '
' + '
'; // 4. 渲染 if (typeof renderHeaderCapsule === 'function') { renderHeaderCapsule('header-mtc-score', html); } } /* --- Metacritic 联动逻辑结束 --- */ let myDramaListContentRating = null; let latestRatingModuleClaims = null; let commonSenseMediaRating = null; let latestCommonSenseRequestKey = null; function getCommonSenseMediaSearchInfo() { const titleNodes = [ document.querySelector('h1 [property="v:itemreviewed"]'), document.querySelector('h1 [property="v:itemregulated"]'), document.querySelector('h1 span'), document.querySelector('h1') ].filter(Boolean); const titles = []; titleNodes.forEach(node => { const title = node.textContent .replace(/\(\d{4}\)\s*$/, '') .trim(); if (title && !titles.includes(title)) { titles.push(title); } }); const infoText = document.querySelector('#info')?.innerText || ''; const originalTitle = infoText.match(/(?:原名|又名):\s*([^\n/]+)/)?.[1]?.trim(); if (originalTitle && !titles.includes(originalTitle)) { titles.push(originalTitle); } const aliasesLine = infoText.match(/又名:\s*([^\n]+)/)?.[1]; if (aliasesLine) { aliasesLine.split('/').forEach(item => { const alias = item.trim(); if (alias && !titles.includes(alias)) { titles.push(alias); } }); } const year = document.querySelector('.year')?.textContent.match(/\d{4}/)?.[0] || ''; return { titles, year }; } function slugifyCommonSenseMediaTitle(title) { return String(title || '') .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') .toLowerCase() .replace(/&/g, ' and ') .replace(/[^a-z0-9\s]/g, '') .trim() .replace(/\s+/g, '-'); } function parseCommonSenseMediaRating(doc, rawHtml = '') { const selectors = [ '.rating__age', '[class*="rating__age"]', '[data-testid*="age"]' ]; let text = ''; for (const selector of selectors) { const node = doc.querySelector(selector); if (node?.textContent?.trim()) { text = node.textContent; break; } } // 页面结构变更或服务端 HTML 与 DOM 结构不一致时的兜底。 if (!text && rawHtml) { const patterns = [ /class=["'][^"']*rating__age[^"']*["'][^>]*>\s*([^<]+)/i, /["']recommendedAge["']\s*:\s*["']?(\d{1,2}\+?)["']?/i, /["']age["']\s*:\s*["']?(\d{1,2}\+?)["']?/i ]; for (const pattern of patterns) { const match = rawHtml.match(pattern); if (match?.[1]) { text = match[1]; break; } } } const ageMatch = String(text).match(/\b(\d{1,2})\s*\+?\b/); if (!ageMatch) return null; return `${ageMatch[1]}+`; } function requestCommonSenseMedia(url) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url, timeout: 15000, headers: { Accept: 'text/html,application/xhtml+xml', 'Accept-Language': 'en-US,en;q=0.9' }, onload(response) { if (response.status >= 200 && response.status < 400) { resolve(response.responseText); return; } reject( new Error( `Common Sense Media 请求失败,状态码:${response.status}` ) ); }, ontimeout() { reject(new Error('Common Sense Media 请求超时')); }, onerror() { reject(new Error('Common Sense Media 网络请求失败')); } }); }); } async function fetchCommonSenseMediaRating() { const { titles } = getCommonSenseMediaSearchInfo(); for (const title of titles) { const slug = slugifyCommonSenseMediaTitle(title); if (!slug) continue; const url = `https://www.commonsensemedia.org/movie-reviews/${slug}`; try { const html = await requestCommonSenseMedia(url); const doc = new DOMParser().parseFromString(html, 'text/html'); const rating = parseCommonSenseMediaRating(doc, html); if (rating) { return rating; } } catch (error) { // 标题/别名有多个,单个 URL 不存在时继续尝试。 console.debug(`Common Sense Media 查询失败:${title}`, error); } } return null; } function processCommonSenseMedia() { const { titles, year } = getCommonSenseMediaSearchInfo(); if (!titles.length) return; // 防止页面上的其他异步逻辑或重复初始化重复请求。 const requestKey = `${titles.join('|')}|${year}`; if (latestCommonSenseRequestKey === requestKey) return; latestCommonSenseRequestKey = requestKey; fetchCommonSenseMediaRating() .then(rating => { commonSenseMediaRating = rating || null; if (latestRatingModuleClaims) { renderRatingModule(latestRatingModuleClaims); } }) .catch(error => { commonSenseMediaRating = null; console.warn('Common Sense Media 信息加载失败:', error); if (latestRatingModuleClaims) { renderRatingModule(latestRatingModuleClaims); } }); } function parseMyDramaListContentRating(doc, rawHtml = '') { const ratingNode = doc.querySelector('li.content-rating'); let text = ratingNode?.textContent || ''; if (!text && rawHtml) { const match = rawHtml.match( /Content\s*Rating:\s*<\/[^>]+>\s*([^<\n]+?)(?:\s*<\/li>|<)/i ); text = match?.[1] || ''; } text = text .replace(/Content\s*Rating\s*:/i, '') .trim(); if ( !text || /^(?:not\s*yet\s*rated|unrated|unknown|n\/a|none|null|-)+$/i.test(text) ) { return null; } // 必须从字符串开头匹配。 const match = text.match( /^(?:\d{1,2}\s*\+|G|PG(?:\s*-\s*\d{1,2})?|NC\s*-\s*17|R\s*-\s*\d{1,2}|R15\+|R18\+|PG12|I{1,3}[AB]?|AL|\d{1,2})(?=\s|$|-)/ ); if (!match) return null; return match[0] .replace(/\s+/g, '') .toUpperCase(); } async function fetchMyDramaListContentRating(result) { if (!result?.url) return null; const html = await requestMyDramaList(result.url); const doc = new DOMParser().parseFromString( html, 'text/html' ); return parseMyDramaListContentRating(doc, html); } function processMyDramaList() { const block = document.getElementById('block-mydramalist'); if (!block) return; const titleInfo = getMyDramaListSearchInfo(); if (!titleInfo.titles.length) return; searchMyDramaListTitle(titleInfo) .then(async result => { if (!result) return; // 同一详情页只请求一次: // 评分和 Content Rating 一起解析。 const html = await requestMyDramaList(result.url); const doc = new DOMParser().parseFromString( html, 'text/html' ); const ratingData = parseMyDramaListRating(doc, html); const contentRating = parseMyDramaListContentRating(doc, html); return { ...result, ...ratingData, contentRating }; }) .then(data => { if (!data) return; // 原本的 MyDL 评分侧栏。 if (data.score) { renderMyDramaListRating(data); } // MyDL 分级成功时,保存并刷新“影视分级”模块。 // `null` 也要写入缓存,确保 Not Yet Rated 时旧 MyDL 卡片被移除。 myDramaListContentRating = data.contentRating || null; if (latestRatingModuleClaims) { renderRatingModule(latestRatingModuleClaims); } }) .catch(error => { console.warn('MyDramaList 信息加载失败:', error); }); } function getMyDramaListSearchInfo() { const titleNodes = [ document.querySelector('h1 [property="v:itemreviewed"]'), document.querySelector('h1 [property="v:itemregulated"]'), document.querySelector('h1 span'), document.querySelector('h1') ].filter(Boolean); const titles = []; titleNodes.forEach(node => { const title = node.textContent .replace(/\(\d{4}\)\s*$/, '') .trim(); if (title && !titles.includes(title)) { titles.push(title); } }); const infoText = document.querySelector('#info')?.innerText || ''; const originalTitle = infoText.match(/(?:原名|又名):\s*([^\n/]+)/)?.[1]?.trim(); if (originalTitle && !titles.includes(originalTitle)) { titles.push(originalTitle); } const aliasesLine = infoText.match(/又名:\s*([^\n]+)/)?.[1]; if (aliasesLine) { aliasesLine.split('/').forEach(item => { const alias = item.trim(); if (alias && !titles.includes(alias)) { titles.push(alias); } }); } const year = document.querySelector('.year')?.textContent.match(/\d{4}/)?.[0] || ''; return { titles, year }; } async function searchMyDramaListTitle(titleInfo) { const resultMap = new Map(); // 搜索所有标题,再统一选择最可信的候选。 // 不能在单个关键词找到一个弱匹配后立即返回。 for (const title of titleInfo.titles) { if (!title) continue; try { const html = await requestMyDramaList( `https://mydramalist.com/search?q=${encodeURIComponent(title)}` ); const doc = new DOMParser().parseFromString(html, 'text/html'); const candidates = parseMyDramaListSearchResults(doc); candidates.forEach(candidate => { const existing = resultMap.get(candidate.url); if (!existing) { resultMap.set(candidate.url, candidate); return; } // 同一个详情页可能被多个链接解析出来,合并标题。 candidate.titles.forEach(candidateTitle => { if (!existing.titles.includes(candidateTitle)) { existing.titles.push(candidateTitle); } }); if (!existing.year && candidate.year) { existing.year = candidate.year; } }); } catch (error) { console.warn(`MyDramaList 搜索失败:${title}`, error); } } if (!resultMap.size) return null; return chooseMyDramaListCandidate( [...resultMap.values()], titleInfo.titles, titleInfo.year ); } function parseMyDramaListSearchResults(doc) { const resultMap = new Map(); // 优先从真正的搜索结果卡片中取详情链接,避免抓到导航栏、 // 推荐区、排行榜及页面中其他无关链接。 const containers = [ ...doc.querySelectorAll( '.film-list .item, ' + '.film-list .box, ' + '.search-results .item, ' + '.search-results .box, ' + '.col-lg-8 .box' ) ]; containers.forEach(card => { const links = [...card.querySelectorAll('a[href]')]; const detailLink = links.find(link => { const href = link.getAttribute('href') || ''; return /^\/\d+-[^/?#]+\/?(?:[?#].*)?$/.test(href); }); if (!detailLink) return; const href = detailLink.getAttribute('href') || ''; const url = new URL(href, 'https://mydramalist.com').href .replace(/[?#].*$/, '') .replace(/\/$/, ''); const titles = []; const addTitle = value => { const title = String(value || '') .replace(/\s+/g, ' ') .trim(); if ( title && title.length <= 150 && !titles.includes(title) ) { titles.push(title); } }; addTitle(detailLink.getAttribute('title')); addTitle(detailLink.textContent); // 搜索卡片中可能同时包含英文标题和原始标题。 card.querySelectorAll( '.title, .text-primary, .text-muted, h2, h3, h4' ).forEach(element => { addTitle(element.textContent); }); const cardText = (card.innerText || '') .replace(/\s+/g, ' ') .trim(); const year = cardText.match(/\b(?:19|20)\d{2}\b/)?.[0] || ''; if (!titles.length) return; const existing = resultMap.get(url); if (existing) { titles.forEach(title => { if (!existing.titles.includes(title)) { existing.titles.push(title); } }); if (!existing.year && year) { existing.year = year; } return; } resultMap.set(url, { title: titles[0], titles, year, url }); }); return [...resultMap.values()]; } function chooseMyDramaListCandidate(candidates, sourceTitles, expectedYear) { const validSourceTitles = sourceTitles .map(title => ({ raw: String(title || '').trim(), normalized: normalizeMyDramaListTitle(title) })) .filter(item => item.normalized); let bestCandidate = null; let bestScore = -Infinity; let bestMatchType = ''; candidates.forEach(candidate => { const candidateTitles = ( candidate.titles?.length ? candidate.titles : [candidate.title] ) .map(title => ({ raw: String(title || '').trim(), normalized: normalizeMyDramaListTitle(title) })) .filter(item => item.normalized); let titleScore = -Infinity; let matchType = ''; validSourceTitles.forEach(sourceTitle => { candidateTitles.forEach(candidateTitle => { const match = scoreMyDramaListTitlePair( sourceTitle.raw, candidateTitle.raw ); if (match.score > titleScore) { titleScore = match.score; matchType = match.type; } }); }); if (!Number.isFinite(titleScore)) return; let totalScore = titleScore; if (expectedYear && candidate.year) { const yearDifference = Math.abs( Number(expectedYear) - Number(candidate.year) ); // 同一作品在不同地区上线可能跨一年。 if (yearDifference === 0) { totalScore += 15; } else if (yearDifference === 1) { totalScore += 4; } else { // 年份相差两年以上时直接排除。 return; } } if (totalScore > bestScore) { bestScore = totalScore; bestCandidate = candidate; bestMatchType = matchType; } }); if (!bestCandidate) return null; /* * 严格标题相等可以直接接受。 * 拉丁标题的高相似匹配要求更高阈值。 * 单纯包含关系不能作为可靠匹配依据。 */ const accepted = bestMatchType === 'exact' || bestMatchType === 'exact-number-equivalent' || ( bestMatchType === 'latin-similar' && bestScore >= 88 ); if (!accepted) { console.debug('MyDramaList 未找到可信匹配:', { sourceTitles, expectedYear, bestCandidate, bestScore, bestMatchType }); return null; } return bestCandidate; } function scoreMyDramaListTitlePair(sourceTitle, candidateTitle) { const source = normalizeMyDramaListTitle(sourceTitle); const candidate = normalizeMyDramaListTitle(candidateTitle); if (!source || !candidate) { return { score: 0, type: 'none' }; } if (source === candidate) { return { score: 100, type: 'exact' }; } /* * 统一常见的续集数字表达: * 2、Ⅱ、II、Part 2 等可以互相比较。 */ const sourceNumberNormalized = normalizeMyDramaListSequenceNumber(sourceTitle); const candidateNumberNormalized = normalizeMyDramaListSequenceNumber(candidateTitle); if ( sourceNumberNormalized && sourceNumberNormalized === candidateNumberNormalized ) { return { score: 98, type: 'exact-number-equivalent' }; } // 任意一边包含中日韩文字时,只接受严格匹配。 // 不使用“共同字符数量”,否则中文短标题极易误匹配。 if ( containsMyDramaListCjk(sourceTitle) || containsMyDramaListCjk(candidateTitle) ) { return { score: 0, type: 'cjk-mismatch' }; } // 续集编号不同,直接排除。 if (!haveCompatibleMyDramaListSequenceNumbers( sourceTitle, candidateTitle )) { return { score: 0, type: 'sequence-mismatch' }; } const sourceTokens = tokenizeMyDramaListLatinTitle(sourceTitle); const candidateTokens = tokenizeMyDramaListLatinTitle(candidateTitle); if (!sourceTokens.length || !candidateTokens.length) { return { score: 0, type: 'none' }; } const tokenScore = getMyDramaListTokenSimilarity( sourceTokens, candidateTokens ); const editScore = getMyDramaListEditSimilarity( sourceTokens.join(''), candidateTokens.join('') ); // token 相似度占主导,编辑距离用于辅助处理轻微拼写差异。 const similarity = tokenScore * 0.7 + editScore * 0.3; return { score: similarity * 100, type: similarity >= 0.85 ? 'latin-similar' : 'latin-mismatch' }; } function normalizeMyDramaListTitle(title) { return String(title || '') .toLowerCase() .normalize('NFKC') .replace(/\(\s*(?:19|20)\d{2}\s*\)/g, '') .replace(/\b(?:19|20)\d{2}\b/g, '') .replace(/&/g, 'and') .replace(/[^\p{L}\p{N}]+/gu, ''); } function normalizeMyDramaListSequenceNumber(title) { return String(title || '') .toLowerCase() .normalize('NFKC') .replace(/\(\s*(?:19|20)\d{2}\s*\)/g, '') .replace(/\b(?:19|20)\d{2}\b/g, '') .replace(/\bpart\s*(\d+)\b/gi, '$1') .replace(/\bseason\s*(\d+)\b/gi, '$1') .replace(/第\s*([一二三四五六七八九十\d]+)\s*[部季]/g, '$1') .replace(/ⅰ{3}/g, '3') .replace(/ⅱ/g, '2') .replace(/\biii\b/g, '3') .replace(/\bii\b/g, '2') .replace(/[^a-z0-9\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]+/gu, ''); } function containsMyDramaListCjk(value) { return /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u .test(String(value || '')); } function extractMyDramaListSequenceNumbers(title) { const value = String(title || '') .toLowerCase() .normalize('NFKC') .replace(/\b(?:19|20)\d{2}\b/g, ''); const numbers = new Set(); for (const match of value.matchAll( /(?:\bpart\s*|\bseason\s*|第\s*)?(\d+)(?:\s*[部季])?/g )) { numbers.add(Number(match[1])); } if (/\bii\b|ⅱ/u.test(value)) numbers.add(2); if (/\biii\b|ⅲ/u.test(value)) numbers.add(3); return [...numbers]; } function haveCompatibleMyDramaListSequenceNumbers(a, b) { const numbersA = extractMyDramaListSequenceNumbers(a); const numbersB = extractMyDramaListSequenceNumbers(b); if (!numbersA.length && !numbersB.length) return true; if (!numbersA.length || !numbersB.length) return false; return numbersA.some(number => numbersB.includes(number)); } function tokenizeMyDramaListLatinTitle(title) { const ignoredWords = new Set([ 'a', 'an', 'the', 'of', 'and', 'to', 'in', 'on', 'for' ]); return String(title || '') .toLowerCase() .normalize('NFKD') .replace(/[\u0300-\u036f]/g, '') .replace(/\b(?:19|20)\d{2}\b/g, '') .replace(/&/g, ' and ') .split(/[^\p{L}\p{N}]+/u) .filter(token => token && !ignoredWords.has(token)); } function getMyDramaListTokenSimilarity(tokensA, tokensB) { const setA = new Set(tokensA); const setB = new Set(tokensB); let intersection = 0; setA.forEach(token => { if (setB.has(token)) intersection++; }); if (!intersection) return 0; // Sørensen–Dice 系数。 return (2 * intersection) / (setA.size + setB.size); } function getMyDramaListEditSimilarity(a, b) { if (!a || !b) return 0; if (a === b) return 1; const previous = Array.from( { length: b.length + 1 }, (_, index) => index ); for (let i = 1; i <= a.length; i++) { const current = [i]; for (let j = 1; j <= b.length; j++) { current[j] = Math.min( current[j - 1] + 1, previous[j] + 1, previous[j - 1] + ( a[i - 1] === b[j - 1] ? 0 : 1 ) ); } previous.splice(0, previous.length, ...current); } return 1 - previous[b.length] / Math.max(a.length, b.length); } async function fetchMyDramaListRating(result) { const html = await requestMyDramaList(result.url); const doc = new DOMParser().parseFromString(html, 'text/html'); const ratingData = parseMyDramaListRating(doc, html); if (!ratingData || !ratingData.score) return null; return { ...result, ...ratingData }; } function parseMyDramaListRating(doc, rawHtml) { let score = ''; let votes = ''; // 用户提供的页面结构: // .col-film-rating .box.deep-orange => 8.5 score = doc.querySelector('.col-film-rating .box.deep-orange')?.textContent.trim() || doc.querySelector('.col-film-rating .box')?.textContent.trim() || ''; // Ratings: 8.5/10 from 7,188 users const ratingText = [ ...doc.querySelectorAll('.hfs') ].find(element => /Ratings?\s*:/i.test(element.textContent || '')) ?.textContent .replace(/\s+/g, ' ') .trim() || ''; if (!score) { score = ratingText.match(/Ratings?\s*:\s*([\d.]+)\s*\/\s*10/i)?.[1] || ''; } votes = ratingText.match(/from\s+([\d,.\s]+)\s+users?/i)?.[1]?.trim() || ''; // 兼容结构变化 if (!score) { score = doc.querySelector('[itempropx="ratingValue"]')?.textContent.trim() || doc.querySelector('[itemprop="ratingValue"]')?.textContent.trim() || ''; } // JSON-LD 兜底 if (!score) { const jsonLdElements = [ ...doc.querySelectorAll('script[type="application/ld+json"]') ]; for (const element of jsonLdElements) { try { const value = JSON.parse(element.textContent); const entries = Array.isArray(value) ? value : [value]; for (const entry of entries) { const aggregate = entry?.aggregateRating; if (aggregate?.ratingValue) { score = String(aggregate.ratingValue); votes = String( aggregate.ratingCount || aggregate.reviewCount || votes ); break; } } } catch (error) { // 忽略无效 JSON-LD。 } if (score) break; } } // 原始 HTML 正则最终兜底 if (!score) { score = rawHtml.match( /Ratings?\s*:\s*(?:<[^>]+>\s*)*([\d.]+)\s*(?:<[^>]+>\s*)*\/\s*10/i )?.[1] || rawHtml.match( /class=["'][^"']*\bbox\b[^"']*\bdeep-orange\b[^"']*["'][^>]*>\s*([\d.]+)/ )?.[1] || ''; } if (!votes) { votes = rawHtml.match(/from\s+([\d,.\s]+)\s+users?/i)?.[1]?.trim() || ''; } const numericScore = Number.parseFloat(score); if ( !Number.isFinite(numericScore) || numericScore < 0 || numericScore > 10 ) { return null; } return { score: numericScore.toFixed(1), votes: votes.replace(/\s+/g, '') }; } function renderMyDramaListRating(data) { const score = Number.parseFloat(data.score); if (!Number.isFinite(score)) return; // 完全复用 IMDb / TMDB / NeoDB 的侧栏评分模板。 // 因而字体、大小、星星、评价数、分隔线均保持一致。 renderScoreToBlock( 'block-mydramalist', 'MyDL评分', score.toFixed(1), data.votes || '0', data.url ); // MyDL 经常最后才返回;主动要求客观评分补算。 setTimeout(renderObjectiveRating, 0); } function requestMyDramaList(url) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url, headers: { 'Accept': 'text/html,application/xhtml+xml', 'Accept-Language': 'en-US,en;q=0.9', 'Referer': 'https://mydramalist.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' + 'AppleWebKit/537.36 (KHTML, like Gecko) ' + 'Chrome/131.0.0.0 Safari/537.36' }, timeout: 15000, onload(response) { if ( response.status >= 200 && response.status < 400 && response.responseText ) { resolve(response.responseText); return; } reject( new Error( `MyDramaList 请求失败,状态码:${response.status}` ) ); }, ontimeout() { reject(new Error('MyDramaList 请求超时')); }, onerror() { reject(new Error('MyDramaList 网络请求失败')); } }); }); } function escapeMyDramaListHtml(value) { return String(value ?? '') .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } // ================================================================ // 核心逻辑:Wikidata 桥梁与双评分系统 // ================================================================ // 1. Wikidata 统一查询 (一次请求获取多个 ID 和各地区译名) function getExtraIdsFromWikidata(imdbId, callback) { if (!imdbId) return; const searchUrl = "https://www.wikidata.org/w/api.php?action=query&list=search&srsearch=haswbstatement:P345=" + imdbId + "&format=json&srnamespace=0"; GM_xmlhttpRequest({ method: "GET", url: searchUrl, onload: function(res) { try { const searchData = JSON.parse(res.responseText); const entityId = searchData.query.search[0]?.title; if (!entityId) { callback({}); return; } const entityUrl = "https://www.wikidata.org/w/api.php?action=wbgetentities&ids=" + entityId + "&props=claims|labels&format=json"; GM_xmlhttpRequest({ method: "GET", url: entityUrl, onload: function(res2) { try { const data = JSON.parse(res2.responseText); const entity = data.entities[entityId]; callback({ mcId: entity.claims.P1712?.[0]?.mainsnak?.datavalue?.value, allocineId: entity.claims.P1265?.[0]?.mainsnak?.datavalue?.value, labels: entity.labels || {}, claims: entity.claims || {} // 必须包含这一行 }); } catch (e) { callback({}); } } }); } catch (e) { callback({}); } } }); } // 影视分级全能版 function renderRatingModule(claims) { if (!claims) return; // MyDL 异步分级返回后,需要拿这份 Wikidata 数据重新渲染。 latestRatingModuleClaims = claims; const RATING_DB = { // MPA (P1657) "Q219557": "G (全年龄)", "Q18665337": "G (全年龄)", "Q219555": "PG (建议陪同)", "Q18665338": "PG (建议陪同)", "Q18665334": "PG (建议陪同)", // 千与千寻专用 "Q219554": "PG-13 (13+)", "Q18665339": "PG-13 (13+)", "Q219552": "R (17+)", "Q18665340": "R (17+)", "Q18665344": "R (17+)", "Q219553": "NC-17 (18+)", "Q18665341": "NC-17 (18+)", // EIRIN (P2756 & P1144 - 日本) "Q23790275": "G (全年龄)", "Q6708782": "G (全年龄)", "Q23790278": "PG12 (12+)", "Q23790279": "PG12 (12+)", "Q6708785": "PG12 (12+)", "Q23790281": "R15+ (15+)", "Q6708788": "R15+ (15+)", "Q23790282": "R18+ (18+)", "Q6708790": "R18+ (18+)", // Kijkwijzer (P2684 & P1142 - 荷兰) "Q23649977": "AL (全年龄)", "Q12061936": "AL (全年龄)", "Q23649978": "6 (6+)", "Q12061937": "6 (6+)", "Q23649981": "9 (9+)", "Q23649982": "9 (9+)","Q12061938": "9 (9+)", "Q23649983": "12 (12+)", "Q12061939": "12 (12+)", "Q108130768": "14 (14+)", "Q23649984": "16 (16+)", "Q12061940": "16 (16+)", "Q112246473": "18 (18+)", // ClassInd (P3216 & P2334 - 巴西) "Q26678725": "L (全年龄)", "Q26678731": "L (全年龄)", "Q26678730": "10 (10+)", "Q26678733": "12 (12+)", "Q26678735": "14 (14+)", "Q26678737": "16 (16+)", "Q26678741": "18 (18+)", // IFCO (P1981 - 爱尔兰) "Q74434521": "G (全年龄)","Q74434523": "G (全年龄)", "Q74434526": "PG (建议陪同)", "Q74434531": "12A (12+)", "Q74434535": "15A (15+)", "Q74434539": "16 (16+)", "Q74434542": "18 (18+)", // Hong Kong (P8874 - 香港) "Q10563603": "I (全年龄)","Q100711980": "I (全年龄)", "Q10563604": "IIA (12+)", "Q10563605": "IIB (15+)","Q100711984": "IIB (15+)", "Q10563606": "III (18+)", }; const PROPS = [ { id: 'P1657', name: 'MPA', country: '美国' }, { id: 'P2756', name: 'EIRIN', country: '日本' }, { id: 'P1144', name: 'EIRIN', country: '日本' }, { id: 'P2684', name: 'Kijkw', country: '荷兰' }, { id: 'P1142', name: 'Kijkw', country: '荷兰' }, { id: 'P3216', name: 'ClassI', country: '巴西' }, { id: 'P2334', name: 'ClassI', country: '巴西' }, { id: 'P1981', name: 'IFCO', country: '爱尔兰' }, { id: 'P7573', name: 'IFCO', country: '爱尔兰' }, { id: 'P8874', name: 'HK', country: '中国香港' } ]; const ratingGroups = new Map(); PROPS.forEach(prop => { const propertyClaims = claims[prop.id]; if (!Array.isArray(propertyClaims)) return; const ratings = []; propertyClaims.forEach(claim => { const value = claim?.mainsnak?.datavalue?.value; const key = typeof value === 'object' ? value?.id : value; const rating = key ? RATING_DB[key] : null; if (rating && !ratings.includes(rating)) { ratings.push(rating); } }); if (!ratings.length) return; const previous = ratingGroups.get(prop.name); if (previous) { ratings.forEach(rating => { if (!previous.ratings.includes(rating)) { previous.ratings.push(rating); } }); return; } ratingGroups.set(prop.name, { name: prop.name, country: prop.country, ratings }); }); if (myDramaListContentRating) { ratingGroups.set('MyDL', { name: 'MyDL', country: '国际', ratings: [myDramaListContentRating] }); } if (commonSenseMediaRating) { ratingGroups.set('CSM', { name: 'CSM', country: '美国', ratings: [commonSenseMediaRating] }); } // 即便 Wikidata 没有任何分级,只要 MyDL 或 CSM 有信息,也照样显示模块。 if (!ratingGroups.size) return; const getRatingDescription = (rating) => { const text = String(rating).trim(); /* * MyDramaList 通常使用纯年龄码,例如: * 13+、15+、18+ * * 但 G 是例外,不代表年龄,而是 General Audience, * 即全年龄观众均可观看。 */ if (/^G$/i.test(text)) { return '全年龄可观看'; } // MyDL 返回纯年龄码,例如 13+。 if (/^\d+\+$/.test(text)) { return `适合 ${text.replace('+', ' 岁以上')}`; } const match = text.match(/\(([^)]+)\)/); const detail = match?.[1] || ''; if (detail === '全年龄') return '全年龄可观看'; if (detail === '建议陪同') { return '建议家长陪同'; } if (/^\d+\+$/.test(detail)) { return `适合 ${detail.replace('+', ' 岁以上')}`; } return detail || '分级信息'; }; const getRatingCode = (rating) => { return String(rating) .replace(/\s*\([^)]+\)/, '') .trim(); }; const htmlItems = [...ratingGroups.values()] .map(({ name, country, ratings }) => { const rating = ratings.join(' / '); const code = ratings.map(getRatingCode).join(' / '); const description = ratings .map(getRatingDescription) .filter(Boolean) .join(' / '); return `
  • ${name} ${country}
    ${code} ${description}
  • `; }) .join(''); const aside = document.querySelector('.aside'); if (!aside) return; document.getElementById('db-movie-ratings-pro')?.remove(); const ratingDiv = document.createElement('div'); ratingDiv.className = 'indent'; ratingDiv.id = 'db-movie-ratings-pro'; ratingDiv.style.marginBottom = '30px'; ratingDiv.innerHTML = `

    影视分级 · · · · · ·

    `; insertAsideModule(ratingDiv); } // --- 影视名称(基于 Box Office Mojo 页面高效解析,避免额外请求 IMDb) --- function addMediaTitle() { // 防止重复添加 if ($('#info').find('span.pl:contains("影视名称")').length) return; var year = ''; try { year = $('span.year').text().match(/\d+/)[0]; } catch (e) {} var ch_name = $('h1').find('span:first').text().split(' ')[0]; // 清洗规则 function formatName(str) { return str.replace(/\s+/g, ' ') .replace(/ /g, '.') .replace(/:\./, '.') .replace('-.', '-') .replace('..', '.') .replace('.-', '-') .replace(/\.+$/, ''); // ★ 确保末尾没有 . } function appendName(en_name) { var raw = en_name ? `${ch_name} ${en_name} ${year}` : `${ch_name} ${year}`; var name = formatName(raw); var html = `影视名称: ${name}
    `; $('#info').append(html); } // 兜底逻辑:无 IMDb 时从“又名”中提取英文名 function fallbackAkaName() { var en_name = null; try { var akaNode = $('#info span.pl:contains("又名")')[0]; if (akaNode && akaNode.nextSibling) { akaNode.nextSibling.textContent.trim().split('/').forEach(function (e) { e = e.trim(); if (e && e.match(/^[a-zA-Z0-9 '-:]*$/)) en_name = e; }); } } catch (err) {} appendName(en_name); } var imdbMatch = $('#info').html().match(/tt\d+/i); if (!imdbMatch) { fallbackAkaName(); return; } // 改为请求 Box Office Mojo 页面来获取影片英文标题 GM_xmlhttpRequest({ method: 'GET', url: 'https://www.boxofficemojo.com/title/' + imdbMatch[0] + '/', timeout: 15000, headers: { 'Accept-Language': 'en-US,en;q=0.9', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }, onload: function (res) { try { var doc = new DOMParser().parseFromString(res.responseText, 'text/html'); var pageTitle = doc.querySelector('title')?.textContent || ''; var en_name = pageTitle.split('-')[0].trim(); if (!en_name || en_name.toLowerCase().includes('box office mojo')) { en_name = doc.querySelector('h1.a-size-extra-large, h1[class*="a-size-extra-large"]')?.textContent?.trim() || ''; } // 剧集:拼接季号 Sxx if ($('span.pl:contains("季数")').length) { var number = $('#season option:selected').text().trim(); if (!number) { var sn = $('span.pl:contains("季数")')[0]; if (sn && sn.nextSibling) number = sn.nextSibling.textContent.trim(); } if (number) { if (number.length < 2) number = '0' + number; en_name = en_name + ' S' + number; } } appendName(en_name || null); } catch (err) { console.warn('影视名称生成失败:', err); fallbackAkaName(); } }, onerror: fallbackAkaName, ontimeout: fallbackAkaName }); } // ==================== 电影收支模块(基于 Box Office Mojo 高效获取 + 保留全套汇率折算) ==================== const DB_EXCHANGE_RATE_CACHE_KEY = 'db_movie_exchange_rates_v2'; const DB_EXCHANGE_RATE_CACHE_TTL = 24 * 60 * 60 * 1000; const DB_EXCHANGE_RATE_API = 'https://api.frankfurter.dev/v1/latest?base=USD&symbols=JPY,CNY,EUR,GBP,HKD,INR,TWD,CHF,CAD'; async function getLiveExchangeRates() { const fallbackRates = { USD: 1, JPY: 155, CNY: 7.25, EUR: 0.93, GBP: 0.79, HKD: 7.8, INR: 83.5, TWD: 31.8, CHF: 0.88, CAD: 1.37 }; try { const cacheText = localStorage.getItem( DB_EXCHANGE_RATE_CACHE_KEY ); if (cacheText) { const cache = JSON.parse(cacheText); if ( cache?.timestamp && cache?.rates && Date.now() - cache.timestamp < DB_EXCHANGE_RATE_CACHE_TTL ) { const required = [ 'USD', 'JPY', 'CNY', 'EUR', 'GBP', 'HKD', 'INR', 'TWD', 'CHF', 'CAD' ]; if (required.every(k => typeof cache.rates[k] === 'number')) { return cache.rates; } } } } catch (error) { console.warn('读取汇率缓存失败:', error); } try { const response = await fetch(DB_EXCHANGE_RATE_API, { method: 'GET', cache: 'no-cache' }); if (!response.ok) { throw new Error( `汇率接口请求失败:${response.status}` ); } const data = await response.json(); const rates = { USD: 1, JPY: Number(data.rates?.JPY) || fallbackRates.JPY, CNY: Number(data.rates?.CNY) || fallbackRates.CNY, EUR: Number(data.rates?.EUR) || fallbackRates.EUR, GBP: Number(data.rates?.GBP) || fallbackRates.GBP, HKD: Number(data.rates?.HKD) || fallbackRates.HKD, INR: Number(data.rates?.INR) || fallbackRates.INR, TWD: Number(data.rates?.TWD) || fallbackRates.TWD, CHF: Number(data.rates?.CHF) || fallbackRates.CHF, CAD: Number(data.rates?.CAD) || fallbackRates.CAD }; try { localStorage.setItem( DB_EXCHANGE_RATE_CACHE_KEY, JSON.stringify({ timestamp: Date.now(), rates }) ); } catch (error) { console.warn('写入汇率缓存失败:', error); } return rates; } catch (error) { console.warn( '联网获取汇率失败,使用内置近似汇率:', error ); return fallbackRates; } } function isFilmEntity(claims) { if (!claims || !Array.isArray(claims.P31)) return false; const instanceIds = claims.P31 .map(item => item?.mainsnak?.datavalue?.value?.id) .filter(Boolean); const tvQids = [ 'Q5398426', // television series 'Q1259759', // television program 'Q15416', // television series episode 'Q24856', // television season 'Q522618' // television miniseries ]; const filmQids = [ 'Q11424', // film 'Q202866', // animated film 'Q20650540', // 日本动画电影 'Q24870', // short film 'Q282430', // documentary film 'Q226730', // silent film 'Q291688' // animated short film ]; return instanceIds.some(id => filmQids.includes(id)) && !instanceIds.some(id => tvQids.includes(id)); } async function fetchMaoyanBoxOffice(movieUrl) { if (!movieUrl) return null; const match = String(movieUrl || '').match(/\/films\/(\d+)/); if (!match) return null; const movieId = match[1]; const awardUrl = `https://www.maoyan.com/ajax/films/${movieId}`; const html = await gmMaoyanRequest(awardUrl); if (!html) return null; const doc = new DOMParser().parseFromString(html, 'text/html'); const items = [...doc.querySelectorAll('.film-mbox-item')]; let chinaOpeningRmbWan = 0; let chinaTotalRmbWan = 0; items.forEach(item => { const names = [...item.querySelectorAll('.mbox-name')].map(el => el.textContent.trim()); if (names.length >= 2) { const val = parseFloat(names[0]); const label = names[1]; if (!isNaN(val) && val > 0) { if (label.includes('首周票房')) { chinaOpeningRmbWan = val; } else if (label.includes('累计票房')) { chinaTotalRmbWan = val; } } } }); return { chinaOpeningRmb: chinaOpeningRmbWan > 0 ? chinaOpeningRmbWan * 10000 : null, chinaTotalRmb: chinaTotalRmbWan > 0 ? chinaTotalRmbWan * 10000 : null }; } function parseMojoMoney(text) { if (!text) return 0; const cleaned = text.replace(/[^0-9.]/g, ''); const value = parseFloat(cleaned); return Number.isFinite(value) && value > 0 ? value : 0; } function fetchMojoBoxOffice(targetId) { return new Promise((resolve, reject) => { const url = `https://www.boxofficemojo.com/title/${targetId}/`; GM_xmlhttpRequest({ method: 'GET', url: url, headers: { 'Accept-Language': 'en-US,en;q=0.9', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }, onload(response) { if (response.status !== 200) { reject(new Error(`Box Office Mojo 返回 HTTP ${response.status}`)); return; } const doc = new DOMParser().parseFromString(response.responseText, 'text/html'); let budget = 0; let usCanada = 0; let openingWeekend = 0; let worldwide = 0; let southKorea = 0; let japan = 0; let hongKong = 0; let taiwan = 0; let mojoChina = 0; const summaryValues = doc.querySelector('.mojo-summary-values') || doc.querySelector('[class*="mojo-summary-values"]'); if (summaryValues && summaryValues.childNodes) { for (let i = 0; i < summaryValues.childNodes.length; i++) { const node = summaryValues.childNodes[i]; if (node.nodeType === Node.ELEMENT_NODE) { const textContent = node.textContent || ''; const moneyEl = node.querySelector('.money'); if (moneyEl) { if (textContent.includes('Budget')) { budget = parseMojoMoney(moneyEl.textContent); } else if (textContent.includes('Domestic Opening')) { openingWeekend = parseMojoMoney(moneyEl.textContent); } } } } } const summaryTable = doc.querySelectorAll('.mojo-performance-summary-table div, [class*="mojo-performance-summary-table"] div'); for (let i = 0; i < summaryTable.length; i++) { const item = summaryTable[i]; const header = item.querySelector('.a-size-small'); const value = item.querySelector('.money'); if (header && value) { const headerText = header.textContent || ''; if (headerText.includes('Domestic')) { usCanada = parseMojoMoney(value.textContent); } else if (headerText.includes('Worldwide')) { worldwide = parseMojoMoney(value.textContent); } } } // 抓取各国家/地区总票房表格行(含 South Korea, Japan, Hong Kong, Taiwan, China) const tableRows = doc.querySelectorAll('table tr'); for (let i = 0; i < tableRows.length; i++) { const row = tableRows[i]; const cells = row.querySelectorAll('td'); if (cells.length >= 3) { const countryName = cells[0].textContent.trim(); // 总票房通常在行内的最后一个 .money 元素中 const moneyEls = row.querySelectorAll('.money'); if (moneyEls.length > 0) { const lastMoneyEl = moneyEls[moneyEls.length - 1]; const moneyVal = parseMojoMoney(lastMoneyEl.textContent); const nameLower = countryName.toLowerCase(); if (nameLower === 'south korea') { southKorea = moneyVal; } else if (nameLower === 'japan') { japan = moneyVal; } else if (nameLower === 'hong kong') { hongKong = moneyVal; } else if (nameLower === 'taiwan') { taiwan = moneyVal; } else if (nameLower === 'china') { mojoChina = moneyVal; } } } } if (!budget && !usCanada && !worldwide && !openingWeekend && !southKorea && !japan && !hongKong && !taiwan && !mojoChina) { reject(new Error('未在 Box Office Mojo 页面提取到有效的收支数据')); return; } resolve({ budget: budget > 0 ? budget : null, usCanada: usCanada > 0 ? usCanada : null, openingWeekend: openingWeekend > 0 ? openingWeekend : null, worldwide: worldwide > 0 ? worldwide : null, southKorea: southKorea > 0 ? southKorea : null, japan: japan > 0 ? japan : null, hongKong: hongKong > 0 ? hongKong : null, taiwan: taiwan > 0 ? taiwan : null, mojoChina: mojoChina > 0 ? mojoChina : null }); }, onerror() { reject(new Error('Box Office Mojo 请求网络错误')); } }); }); } async function renderBoxOfficeModule(claims, imdbId) { if (!claims) return; if (!isFilmEntity(claims)) { console.log('[豆瓣票房] 非电影条目,跳过电影收支模块'); return; } const aside = document.querySelector('.aside'); if (!aside) return; document.getElementById('db-movie-boxoffice-enhanced')?.remove(); const liveRates = await getLiveExchangeRates(); let maoyanBoxOffice = null; try { const title = getDoubanMovieTitle(); if (title) { const maoyanMovie = await getMaoyanMovie(title); if (maoyanMovie?.url) { maoyanBoxOffice = await fetchMaoyanBoxOffice(maoyanMovie.url); } } } catch (e) { console.warn('[豆瓣票房] 猫眼中国票房获取失败:', e); } const currencyToUSD = { Q4917: 1, // USD Q25224: 1 / liveRates.JPY, // JPY:yen(标准货币实体) Q8146: 1 / liveRates.JPY, // JPY:当前 Wikidata 返回的 yen 单位 Q39099: 1 / liveRates.CNY, // CNY Q4916: 1 / liveRates.EUR, // EUR Q25344: 1 / liveRates.GBP, // GBP Q31015: 1 / liveRates.HKD, // HKD Q188: 1 / 1.95583 / liveRates.EUR, // DEM Q208526: 1 / liveRates.TWD, // TWD Q39: 1 / liveRates.CHF, // CHF Q1104069: 1 / liveRates.CAD // CAD:Canadian dollar }; function parseAmount(amount) { const value = parseFloat(amount); return Number.isFinite(value) ? Math.abs(value) : 0; } function getUnitQid(unitUrl) { return unitUrl?.split('/').pop() || 'Q4917'; } function isJapaneseFilm() { const infoText = document.getElementById('info')?.innerText || ''; return /制作国家\/地区[::]\s*日本|制片国家\/地区[::]\s*日本/.test( infoText ); } function convertToUSD(amount, unitUrl) { const number = parseAmount(amount); const currencyQid = getUnitQid(unitUrl); // 只有 Q39099 才是人民币。 // Q8146 虽然在此数据中表示 yen,但绝不能归为人民币。 const isRmbQid = currencyQid === 'Q39099'; const rate = currencyToUSD[currencyQid]; if (!rate) { console.warn( `[豆瓣票房] 未支持的货币单位:${currencyQid},跳过换算` ); return { amount: 0, cnyAmount: 0, isRMB: false, unsupportedCurrency: true }; } const amountInUSD = number * rate; if (isRmbQid) { return { amount: amountInUSD, cnyAmount: number, isRMB: true }; } return { amount: amountInUSD, cnyAmount: amountInUSD * liveRates.CNY, isRMB: false }; } function formatCNYChinese(usd) { if (!Number.isFinite(usd) || usd <= 0) { return '—'; } const cny = usd * liveRates.CNY; if (cny >= 100000000) { return ` ${(cny / 100000000).toFixed(2)} 亿元 `; } if (cny >= 10000) { return ` ${(cny / 10000).toFixed(2)} 万元 `; } return ` ${Math.round(cny)} `; } function formatPureCNY(cny) { if (!Number.isFinite(cny) || cny <= 0) { return '—'; } if (cny >= 100000000) { return ` ${(cny / 100000000).toFixed(2)} 亿元 `; } if (cny >= 10000) { return ` ${(cny / 10000).toFixed(2)} 万元 `; } return ` ${Math.round(cny)} `; } function readFinancialClaim(property) { const claim = claims[property]?.find(item => { return item?.mainsnak?.datavalue?.value?.amount !== undefined; }); if (!claim) return null; const value = claim.mainsnak.datavalue.value; const originalAmount = parseAmount(value.amount); if (!originalAmount) return null; const converted = convertToUSD( value.amount, value.unit, ); if (converted.isRMB) { return { cny: converted.cnyAmount, usd: converted.amount, isRMB: true }; } return { usd: converted.amount, cny: converted.cnyAmount, isRMB: false }; } const cost = readFinancialClaim('P2130'); const boxOffice = readFinancialClaim('P2142'); let mojoBoxOffice = null; if (imdbId) { try { mojoBoxOffice = await fetchMojoBoxOffice(imdbId); } catch (error) { console.warn('[豆瓣票房] Box Office Mojo 票房抓取失败:', error); } } function isReasonableBudget(budget, worldwide) { if (!budget || budget <= 0) return false; if (!worldwide || worldwide <= 0) return budget < 500_000_000; return budget <= worldwide * 10; } const finalCost = cost || ( isReasonableBudget(mojoBoxOffice?.budget, mojoBoxOffice?.worldwide) ? { usd: mojoBoxOffice.budget, isRMB: false, source: 'mojo' } : null ); const finalBoxOffice = boxOffice?.usd ? { ...boxOffice, source: 'wikidata' } : ( mojoBoxOffice?.worldwide ? { usd: mojoBoxOffice.worldwide, source: 'mojo' } : null ); const financeItems = []; function createFinanceCard({ label, value, icon, type = '', featured = false }) { return `
  • ${label}
    ${value}
  • `; } // 大陆首周票房(来自猫眼) if (maoyanBoxOffice?.chinaOpeningRmb) { financeItems.push( createFinanceCard({ label: '大陆首周票房', value: formatPureCNY(maoyanBoxOffice.chinaOpeningRmb), icon: '¥', type: 'is-revenue is-cny' }) ); } // 大陆总票房(来自猫眼) if (maoyanBoxOffice?.chinaTotalRmb) { financeItems.push( createFinanceCard({ label: '大陆总票房', value: formatPureCNY(maoyanBoxOffice.chinaTotalRmb), icon: '¥', type: 'is-revenue is-cny' }) ); } // 香港总票房(来自 Mojo) if (mojoBoxOffice?.hongKong) { financeItems.push( createFinanceCard({ label: '香港总票房', value: formatCNYChinese(mojoBoxOffice.hongKong), icon: '¥', type: 'is-revenue is-usd' }) ); } // 台湾总票房(来自 Mojo) if (mojoBoxOffice?.taiwan) { financeItems.push( createFinanceCard({ label: '台湾总票房', value: formatCNYChinese(mojoBoxOffice.taiwan), icon: '¥', type: 'is-revenue is-usd' }) ); } // 中国总票房(来自 Mojo) if (mojoBoxOffice?.mojoChina) { financeItems.push( createFinanceCard({ label: '中国总票房', value: formatCNYChinese(mojoBoxOffice.mojoChina), icon: '¥', type: 'is-revenue is-usd' }) ); } // 韩国总票房 if (mojoBoxOffice?.southKorea) { financeItems.push( createFinanceCard({ label: '韩国总票房', value: formatCNYChinese(mojoBoxOffice.southKorea), icon: '₩', type: 'is-revenue is-usd' }) ); } // 日本总票房 if (mojoBoxOffice?.japan) { financeItems.push( createFinanceCard({ label: '日本总票房', value: formatCNYChinese(mojoBoxOffice.japan), icon: '¥', type: 'is-revenue is-usd' }) ); } if (mojoBoxOffice?.openingWeekend) { financeItems.push( createFinanceCard({ label: '北美首周票房', value: formatCNYChinese(mojoBoxOffice.openingWeekend), icon: '$', type: 'is-revenue is-usd' }) ); } if (mojoBoxOffice?.usCanada) { financeItems.push( createFinanceCard({ label: '北美总票房', value: formatCNYChinese(mojoBoxOffice.usCanada), icon: '$', type: 'is-revenue is-usd' }) ); } if (finalCost) { financeItems.push( createFinanceCard({ label: '制作成本', value: finalCost.isRMB ? formatPureCNY(finalCost.cny) : formatCNYChinese(finalCost.usd), icon: '⚙', type: 'is-cost' }) ); } if (finalBoxOffice) { financeItems.push( createFinanceCard({ label: '全球票房', value: formatCNYChinese(finalBoxOffice.usd), icon: '💰', type: 'is-global', featured: true }) ); } // 只要没有任何一项有效数据,直接终止渲染,绝不显示空模块 if (financeItems.length === 0) return; let roiHtml = ''; const effectiveBoxOfficeUSD = finalBoxOffice?.usd || ( maoyanBoxOffice?.chinaTotalRmb ? maoyanBoxOffice.chinaTotalRmb / liveRates.CNY : null ); const costUSD = finalCost ? (finalCost.isRMB ? finalCost.cny / liveRates.CNY : finalCost.usd) : 0; if (finalCost && effectiveBoxOfficeUSD && costUSD > 0) { const roi = ((effectiveBoxOfficeUSD - costUSD) / costUSD) * 100; let roiColor = '#8a9490'; let roiLabel = '低于制作成本'; let roiClass = 'is-low'; if (roi >= 500) { roiColor = '#d9362b'; roiLabel = '票房爆发'; roiClass = 'is-explosive'; } else if (roi >= 200) { roiColor = '#b77909'; roiLabel = '高回报'; roiClass = 'is-high'; } else if (roi >= 100) { roiColor = '#14834a'; roiLabel = '表现优异'; roiClass = 'is-excellent'; } else if (roi >= 0) { roiColor = '#5c851a'; roiLabel = '正向回报'; roiClass = 'is-positive'; } const roiSign = roi > 0 ? '+' : ''; roiHtml = `
  • 投资回报率
    ${roiSign}${roi.toFixed(1)}% ${roiLabel}
  • `; } const boxDiv = document.createElement('div'); boxDiv.className = 'indent'; boxDiv.id = 'db-movie-boxoffice-enhanced'; boxDiv.style.marginBottom = '30px'; boxDiv.innerHTML = `

    电影收支 · · · · · ·

    按当前汇率折算人民币,回报率仅供参考。
    `; insertAsideModule(boxDiv); } // 新增:汉字圈名字对比模块(含澳门、日本,过滤条件计入澳门、不计日本) function renderKanjiZoneComparison(labels) { if (!labels) return; // 1. 定义大中华五地配置(计入过滤条件) const gcRegions = [ { name: "中国大陆", langCodes: ["zh-cn", "zh-hans"] }, { name: "中国香港", langCodes: ["zh-hk", "zh-hant-hk"] }, { name: "中国澳门", langCodes: ["zh-mo", "zh-hant-mo"] }, { name: "中国台湾", langCodes: ["zh-tw", "zh-hant-tw"] }, { name: "新加坡", langCodes: ["zh-sg", "zh-hans-sg"] } ]; // 2. 定义日本配置(不计入过滤条件) const jpRegion = { name: "日本", langCodes: ["ja"] }; // 3. 提取大中华五地的有效译名 const gcResults = []; gcRegions.forEach(region => { let value = ""; for (const code of region.langCodes) { if (labels[code] && labels[code].value) { value = labels[code].value.trim(); break; } } if (value) { gcResults.push({ label: region.name, value }); } }); // 大中华五地仅有一项或零项有值,则不显示模块 if (gcResults.length <= 1) return; // 4. 提取日本译名;日本不参与模块显示过滤 const finalResults = [...gcResults]; let jpVal = ""; for (const code of jpRegion.langCodes) { if (labels[code] && labels[code].value) { jpVal = labels[code].value.trim(); break; } } if (jpVal) { finalResults.push({ label: jpRegion.name, value: jpVal }); } // 5. 寻找豆瓣右侧边栏容器并渲染 const aside = document.querySelector(".aside"); if (!aside) return; const comparisonDiv = document.createElement("div"); comparisonDiv.id = "db-kanji-comparison"; comparisonDiv.className = "indent"; const regionCodes = { 中国大陆: "CN", 中国香港: "HK", 中国澳门: "MO", 中国台湾: "TW", 新加坡: "SG", 日本: "JP" }; const regionHints = { 中国大陆: "大陆译名", 中国香港: "香港译名", 中国澳门: "澳门译名", 中国台湾: "台湾译名", 新加坡: "新加坡译名", 日本: "日文片名" }; const escapeHtml = value => String(value) .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); const htmlItems = finalResults.map(item => `
  • ${escapeHtml(item.label)} ${regionCodes[item.label] || ""}
    ${escapeHtml(item.value)} ${regionHints[item.label] || "地区译名"}
  • `).join(""); comparisonDiv.innerHTML = `

    汉字圈名字对比 · · · · · ·

    `; // 位置由统一排序函数决定(位于电影收支之下) insertAsideModule(comparisonDiv); } // 2. 修正后的 Allocine 抓取逻辑 (将法式逗号替换为点号) function fetchAllocineDualScores(acId) { const url = "https://www.allocine.fr/film/fichefilm_gen_cfilm=" + acId + ".html"; GM_xmlhttpRequest({ method: "GET", url: url, onload: function(resp) { if (resp.status !== 200) return; const doc = new DOMParser().parseFromString(resp.responseText, "text/html"); let pressScore = "N/A", userScore = "N/A"; const ratingItems = doc.querySelectorAll('.rating-item'); ratingItems.forEach(item => { const titleEl = item.querySelector('.rating-title'); const noteEl = item.querySelector('.stareval-note'); if (titleEl && noteEl) { const titleText = titleEl.textContent.trim(); // 这里是核心改动:获取文本后立即将 ',' 替换为 '.' const noteText = noteEl.textContent.trim().replace(',', '.'); if (noteText !== "--") { if (titleText.includes("Presse")) { pressScore = noteText; } else if (titleText.includes("Spectateurs")) { userScore = noteText; } } } }); if (pressScore !== "N/A" || userScore !== "N/A") { renderAllocineDoubleCapsule(acId, pressScore, userScore); } } }); } // 3. Allocine 渲染 (按要求配色) function renderAllocineDoubleCapsule(id, press, user) { const html = '
    ' + // 这里删掉了 margin-right '' + // 前半部分:媒体分 (红色背景) '
    ' + // 移除了 filter: brightness(10),保持图标原色 ' ' + '' + press + '' + '
    ' + // 后半部分:用户分 (黄色背景) '
    ' + // 用户图标:使用和你 Meta 评分一样的 👤 图标 '👤' + '' + user + '' + '
    ' + '
    ' + '
    '; renderHeaderCapsule('header-alc-score', html); } function processLetterboxd(imdbId) { const url = "https://letterboxd.com/imdb/" + imdbId; GM_xmlhttpRequest({ method: "GET", url: url, onload: function(res) { const ratingMatch = res.responseText.match(/\"ratingValue\":\s*([0-9.]+)/); if (ratingMatch) { const score = parseFloat(ratingMatch[1]).toFixed(1); const html = `
    ${score}
    `; renderHeaderCapsule('header-lbx-score', html); } } }); } // --- 其他渲染逻辑 --- function processOMDb(imdbId) { GM_xmlhttpRequest({ method: "GET", url: "https://www.omdbapi.com/?i=" + imdbId + "&apikey=thewdb", // 确认apikey正确 onload: function(res) { if (res.status === 200) { const data = JSON.parse(res.responseText); if (data.Response === "True") { // 1. 原有的 IMDb 渲染逻辑 (保持不变) if (data.imdbRating !== 'N/A') { renderScoreToBlock("block-imdb", "IMDb评分", data.imdbRating, data.imdbVotes, "https://www.imdb.com/title/" + imdbId + "/"); } // 2. 插入新的 Metacritic 联动流程 // 注意:这里不再用 .then(),改用回调函数以获得最佳兼容性 getExtraIdsFromWikidata(imdbId, function(ids) { fetchMetacriticDualScores(ids.mcId, data.Title); }); } } } }); } function processTMDB(imdbId) { GM_xmlhttpRequest({ method: "GET", url: `https://api.themoviedb.org/3/find/${imdbId}?external_source=imdb_id`, headers: { "Authorization": tmdbAuth }, onload: function(res) { try { const data = JSON.parse(res.responseText); const result = data.tv_results?.[0] || data.movie_results?.[0]; if (result) { const type = data.tv_results?.length > 0 ? 'tv' : 'movie'; renderScoreToBlock("block-tmdb", "TMDB评分", result.vote_average.toFixed(1), result.vote_count.toLocaleString(), `https://www.themoviedb.org/${type}/${result.id}`); } } catch(e) {} } }); } function processNeoDB(doubanId) { if (!doubanId) return; GM_xmlhttpRequest({ method: "GET", url: "https://neodb.social/api/catalog/fetch?url=https://movie.douban.com/subject/" + doubanId + "/", headers: { "Accept": "application/json" }, onload: function(res) { if (res.status === 200) { try { const data = JSON.parse(res.responseText); if (data && data.rating) { // 渲染至我们刚刚在侧边栏创建的 block-neodb 容器中 renderScoreToBlock("block-neodb", "NeoDB评分", data.rating.toFixed(1), data.rating_count.toLocaleString(), "https://neodb.social" + data.url); } } catch(e) { console.error("NeoDB 解析失败"); } } } }); } function processAniList(imdbId) { const sparql = `SELECT ?anilistID WHERE {?s wdt:P345 "${imdbId}"; wdt:P8729 ?anilistID.}`; GM_xmlhttpRequest({ method: "GET", url: `https://query.wikidata.org/sparql?format=json&query=${encodeURIComponent(sparql)}`, onload: function(res) { try { const anilistId = JSON.parse(res.responseText).results.bindings[0]?.anilistID?.value; if (!anilistId) return; const query = `query ($id: Int) { Media (id: $id, type: ANIME) { id meanScore siteUrl } }`; GM_xmlhttpRequest({ method: "POST", url: "https://graphql.anilist.co", headers: { "Content-Type": "application/json" }, data: JSON.stringify({ query, variables: { id: parseInt(anilistId) } }), onload: function(response) { const result = JSON.parse(response.responseText); const rating = result.data.Media.meanScore; // 原始百分比分数 (如 85) const siteUrl = result.data.Media.siteUrl; if (rating) { // 保持百分比格式,拼接 % const formattedScore = `${rating}%`; // 直接使用脚本统一的 drdm-capsule yellow-cap 样式 const html = `
    ${formattedScore}
    `; renderHeaderCapsule('header-anilist-score', html); } } }); } catch(e) {} } }); } // ==================== 新增:动画评分获取与渲染模块 ==================== // 辅助延迟函数 const randomSleep = (max = 400, min = 200) => new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * (max - min + 1)) + min)); // 1. 获取 Bangumi 评分 function processBangumi(title) { const searchUrl = `https://bgm.tv/subject_search/${encodeURIComponent(title)}?cat=2`; // 获取豆瓣本页面的年份 const yearEl = document.querySelector(".year"); const dbYear = yearEl ? yearEl.textContent.replace(/\(|\)/g, "").trim() : null; GM_xmlhttpRequest({ method: "GET", url: searchUrl, onload: function(res) { try { const parser = new DOMParser(); const doc = parser.parseFromString(res.responseText, "text/html"); const items = doc.querySelectorAll("#browserItemList li"); let matchedResult = null; // 如果豆瓣页面有年份,优先匹配年份一致的项目 if (dbYear && items.length > 0) { for (let i = 0; i < items.length; i++) { const infoEl = items[i].querySelector(".info"); if (infoEl && infoEl.textContent.includes(dbYear)) { matchedResult = items[i]; break; } } } // 如果按年份没有匹配到,默认取第一项 if (!matchedResult && items.length > 0) { matchedResult = items[0]; } if (matchedResult) { const linkEl = matchedResult.querySelector("a.subjectCover"); const scoreEl = matchedResult.querySelector(".fade"); const countEl = matchedResult.querySelector(".tip_j"); if (linkEl && scoreEl) { const bgmUrl = "https://bgm.tv" + linkEl.getAttribute("href"); const score = parseFloat(scoreEl.innerText).toFixed(1); const count = countEl ? countEl.innerText.replace(/[^0-9]/g, "") : "0"; // 渲染到侧边栏,样式与 TMDB 完全保持一致 renderScoreToBlock("block-bangumi", "Bangumi评分", score, parseInt(count).toLocaleString(), bgmUrl); } } } catch (e) { console.error("解析 Bangumi 评分失败", e); } } }); } // 2. 获取 MyAnimeList (MAL) 评分 function processMAL(title) { const searchUrl = `https://myanimelist.net/search/prefix.json?type=anime&keyword=${encodeURIComponent(title)}&v=1`; // 获取豆瓣本页面的年份 const yearEl = document.querySelector(".year"); const dbYear = yearEl ? yearEl.textContent.replace(/\(|\)/g, "").trim() : null; GM_xmlhttpRequest({ method: "GET", url: searchUrl, onload: function(res) { try { const info = JSON.parse(res.responseText); const items = info.categories?.[0]?.items; if (items && items.length > 0) { let matchedItem = null; // 如果豆瓣页面有年份,优先匹配年份一致的项目 if (dbYear) { for (let i = 0; i < items.length; i++) { const item = items[i]; // MAL 返回的 aired 格式通常为 "Oct 2015" 或 "2015" const airedStr = item.payload?.aired || ""; if (airedStr.includes(dbYear)) { matchedItem = item; break; } } } // 如果按年份没匹配到,则默认取第一项 if (!matchedItem) { matchedItem = items[0]; } if (matchedItem && matchedItem.url) { const pageUrl = matchedItem.url; // 延迟请求避免高频被ban randomSleep(300, 100).then(() => { GM_xmlhttpRequest({ method: "GET", url: pageUrl, onload: function(pageRes) { try { const parser = new DOMParser(); const doc = parser.parseFromString(pageRes.responseText, "text/html"); const scoreEl = doc.querySelector(".fl-l.score"); if (scoreEl) { const scoreText = scoreEl.textContent.trim(); // 排除未开播无评分的情况 (N/A) if (scoreText === "N/A" || !scoreText) return; const score = parseFloat(scoreText).toFixed(1); const count = scoreEl.dataset.user ? scoreEl.dataset.user.replace(/users|,/g, "").trim() : "0"; renderScoreToBlock("block-mal", "MAL评分", score, parseInt(count).toLocaleString(), pageUrl); } } catch (err) { console.error("解析 MAL 页面失败", err); } } }); }); } } } catch (e) { console.error("获取 MAL 数据失败", e); } } }); } function renderScoreToBlock(blockId, label, score, votes, href) { const container = document.getElementById(blockId); if (!container || !score || score === "0.0" || score === "N/A") return; const starNum = Math.round(parseFloat(score)) * 5; container.innerHTML = `
    ${score}
    `; } initRankings(); initMain(); injectTrendChart(); setTimeout(function() { injectSteamUI(); }, 200); (function addViewOriginalLogic() { const mainPic = document.querySelector('#mainpic'); if (!mainPic) return; const img = mainPic.querySelector('img'); if (img) { const rawUrl = img.src.replace(/photo\/[sl](_ratio_poster|pic)\/public\/(p\d+).+$/, "photo/l/public/$2.jpg"); const btn = document.createElement('a'); btn.className = 'view-original-btn'; btn.href = rawUrl; btn.target = '_blank'; btn.innerText = '查看原图'; mainPic.appendChild(btn); } })(); // ===================================================================== // --- 复制简介模块(完整版格式增强)--- // ① ◎译  名 / ◎片  名(拆分中英文标题) // ② 完整演职员表:导演 / 演员 / 编剧 / 音乐 / 摄影 / 美术 / 服装 / 动作特技 … // ③ 人名中文与外文名以 " / " 分隔,演员附角色名(仅保留"配/饰"角色,去掉"配音 Voice"前缀) // ④ ◎获奖情况(抓取豆瓣奖项页,位于简介之后) // ===================================================================== // --- 1. 复制简介按钮 --- function addCopyIntroButton() { const mainpic = document.querySelector('#mainpic'); if (!mainpic) return; const allLinks = mainpic.getElementsByTagName('a'); let originalBtn = null; for (let a of allLinks) { if (a.innerText.trim() === '查看原图') { originalBtn = a; break; } } if (!originalBtn || document.getElementById('copy-intro-btn')) return; originalBtn.style.cssText = ` display: inline-block !important; width: 48% !important; float: left !important; text-align: center !important; padding: 6px 0 !important; margin: 10px 0 0 0 !important; box-sizing: border-box !important; font-size: 13px !important; height: auto !important; line-height: normal !important; `; const copyBtn = document.createElement('a'); copyBtn.id = 'copy-intro-btn'; copyBtn.href = 'javascript:void(0);'; copyBtn.innerText = '复制简介'; copyBtn.className = originalBtn.className; copyBtn.style.cssText = ` display: inline-block !important; width: 48% !important; float: right !important; text-align: center !important; padding: 6px 0 !important; margin: 10px 0 0 0 !important; box-sizing: border-box !important; font-size: 13px !important; cursor: pointer !important; height: auto !important; line-height: normal !important; `; copyBtn.onclick = async function (e) { e.preventDefault(); if (copyBtn.dataset.busy === '1') return; copyBtn.dataset.busy = '1'; copyBtn.innerText = '获取中…'; try { const fullContent = await generateMovieInfo(); await _afCopyText(fullContent); copyBtn.innerText = '已复制 ✔'; } catch (err) { console.warn('复制简介失败:', err); copyBtn.innerText = '复制失败 ✘'; } setTimeout(() => { copyBtn.innerText = '复制简介'; copyBtn.dataset.busy = '0'; }, 1500); }; originalBtn.after(copyBtn); const clearer = document.createElement('div'); clearer.style.cssText = "clear: both !important; width: 100% !important; height: 1px !important;"; copyBtn.after(clearer); } // --- 2. 工具函数 --- function _afCopyText(text) { if (navigator.clipboard && window.isSecureContext) { return navigator.clipboard.writeText(text); } return new Promise(function (resolve, reject) { try { if (typeof GM_setClipboard === 'function') { GM_setClipboard(text); resolve(); return; } const ta = document.createElement('textarea'); ta.value = text; ta.style.cssText = 'position:fixed;top:-9999px;opacity:0;'; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); ta.remove(); resolve(); } catch (e) { reject(e); } }); } function _afAddComma(num) { const n = parseInt(String(num).replace(/[^\d]/g, ''), 10); return isNaN(n) ? String(num) : n.toLocaleString('en-US'); } function _afSplitTitle(fullTitle) { fullTitle = (fullTitle || '').trim().replace(/\s+/g, ' '); if (!fullTitle) return { chs: '', original: '' }; const m = fullTitle.match(/^(.+[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff][0-9]*)\s+(\S.*)$/); if (m) return { chs: m[1].trim(), original: m[2].trim() }; if (/[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff]/.test(fullTitle)) return { chs: fullTitle, original: fullTitle }; return { chs: '', original: fullTitle }; } function _afSplitName(fullName) { fullName = (fullName || '').trim().replace(/\s+/g, ' '); if (!fullName) return { chs: '', foreign: '' }; const idx = fullName.indexOf(' '); if (idx > 0 && /[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff]/.test(fullName.slice(0, idx))) { return { chs: fullName.slice(0, idx).trim(), foreign: fullName.slice(idx + 1).trim() }; } if (/[\u3040-\u30ff\u3400-\u4dbf\u4e00-\u9fff]/.test(fullName)) return { chs: fullName, foreign: '' }; return { chs: '', foreign: fullName }; } // --- 3. 抓取并解析豆瓣"演职员"整页(同源 fetch) --- const _afCreditsCache = {}; function _afFetchCredits(subjectId) { if (_afCreditsCache[subjectId]) return _afCreditsCache[subjectId]; _afCreditsCache[subjectId] = fetch('https://movie.douban.com/subject/' + subjectId + '/celebrities', { credentials: 'same-origin' }) .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); }) .then(function (html) { return _afParseCreditsDoc(new DOMParser().parseFromString(html, 'text/html')); }) .catch(function (err) { console.warn('演职员页面获取失败,将退回精简模式:', err); return []; }); return _afCreditsCache[subjectId]; } function _afParseCreditsDoc(doc) { const root = doc.querySelector('#celebrities') || doc; let wrappers = Array.from(root.querySelectorAll('.list-wrapper')); if (!wrappers.length) { wrappers = Array.from(root.querySelectorAll('h2')).filter(function (h) { return h.nextElementSibling && h.nextElementSibling.tagName === 'UL'; }); } const sections = []; for (let w of wrappers) { const h2 = w.tagName === 'H2' ? w : w.querySelector('h2'); if (!h2) continue; const ul = (w.tagName === 'H2' ? w.nextElementSibling : null) || w.querySelector('ul.celebrities-list') || w.querySelector('ul'); if (!ul) continue; const h2c = h2.cloneNode(true); h2c.querySelectorAll('.pl, a').forEach(function (n) { n.remove(); }); let position = h2c.textContent.replace(/\s+/g, ''); position = position.replace(/[A-Za-z]+/g, ''); if (!position) continue; if (position === '主演') position = '演员'; if (/影人|合作|作品/.test(position)) continue; let lis = ul.querySelectorAll('li.celebrity'); if (!lis.length) lis = ul.querySelectorAll('li'); const people = Array.from(lis).map(function (li) { const nameEl = li.querySelector('.name') || li.querySelector('a'); const roleEl = li.querySelector('.role'); const fullName = (nameEl ? nameEl.textContent : '').trim().replace(/\s+/g, ' '); const role = ((roleEl && (roleEl.getAttribute('title') || roleEl.textContent)) || '').trim(); const parts = _afSplitName(fullName); // 提取角色:优先取括号内的 (配 xxx) / (饰 xxx),否则取独立的 饰/配 xxx;纯"配音"则留空 let character = ''; if (role) { const bracketMatch = role.match(/[((]\s*(配|饰)\s+(.+?)\s*[))]/); if (bracketMatch) { character = bracketMatch[1] + ' ' + bracketMatch[2]; } else if (/^\s*(饰|配)\s+/.test(role)) { character = role.replace(/^\s+/, ''); } } return { chs: parts.chs, foreign: parts.foreign, character: character }; }).filter(function (p) { return p.chs || p.foreign; }); if (people.length) sections.push({ position: position, people: people }); } sections.sort(function (a, b) { const rank = function (p) { return p === '导演' ? 0 : (p === '演员' ? 1 : 2); }; return rank(a.position) - rank(b.position); }); return sections; } // --- 4. 渲染演职员(职位与人名平齐,无换行) --- function _afFormatCelebrities(sections) { return sections.map(function (sec) { const position = sec.position; let title = '◎'; switch (position.length) { case 1: title += ' ' + position + '   '; break; case 2: title += position.split('').join('  ') + ' '; break; case 3: title += position.split('').join(' ') + ' '; break; case 4: title += position + ' '; break; default: title += position + ' '; } const people = sec.people.map(function (f, i) { const name = f.chs ? (f.foreign ? f.chs + ' / ' + f.foreign : f.chs) : f.foreign; return (i > 0 ? '      ' : '') + name + (f.character ? ' (' + f.character + ')' : ''); }).join('\n'); return title + people; }).join('\n'); } // --- 4b. 抓取并解析豆瓣"获奖情况"整页 --- const _afAwardsCache = {}; function _afFetchAwards(subjectId) { if (!subjectId) return Promise.resolve([]); if (_afAwardsCache[subjectId] !== undefined) return _afAwardsCache[subjectId]; _afAwardsCache[subjectId] = fetch('https://movie.douban.com/subject/' + subjectId + '/awards/', { credentials: 'same-origin' }) .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); }) .then(function (html) { const doc = new DOMParser().parseFromString(html, 'text/html'); const awardDivs = doc.querySelectorAll('div.awards'); const results = []; awardDivs.forEach(function (div) { const h2 = div.querySelector('.hd > h2'); if (!h2) return; const nameLink = h2.querySelector('a'); const yearSpan = h2.querySelector('.year'); const name = nameLink ? nameLink.textContent.trim() : h2.textContent.trim(); let year = ''; if (yearSpan) { const ym = yearSpan.textContent.match(/\d+/); if (ym) year = ym[0]; } const awardEls = div.querySelectorAll('.award'); const items = []; awardEls.forEach(function (aw) { const lis = aw.querySelectorAll('li'); if (!lis.length) return; const itemName = lis[0].textContent.trim(); let people = []; if (lis[1]) { people = lis[1].textContent.split('/').map(function (s) { return s.trim(); }).filter(Boolean); } items.push({ name: itemName, people: people }); }); if (name && items.length) { results.push({ name: name, year: year, awards: items }); } }); return results; }) .catch(function (err) { console.warn('获奖情况获取失败:', err); return []; }); return _afAwardsCache[subjectId]; } function _afFormatAwards(awards) { if (!awards || !awards.length) return ''; return '◎获奖情况\n\n' + awards.map(function (e) { const awardName = '  ' + e.name + (e.year ? ' (' + e.year + ')' : '') + '\n'; const awardItems = e.awards.map(function (item) { return '  ' + item.name + (item.people && item.people.length ? ' ' + item.people.join(' / ') : ''); }).join('\n'); return awardName + awardItems; }).join('\n\n') + '\n\n'; } // --- 5. IMDb 评分获取 --- const _afImdbCache = {}; function _afGetImdbScore(imdbId) { if (!imdbId) return Promise.resolve(null); if (_afImdbCache[imdbId] !== undefined) return _afImdbCache[imdbId]; _afImdbCache[imdbId] = (async function () { try { const fromDom = _afScrapeImdbFromDom(imdbId); if (fromDom && fromDom.rating) return fromDom; } catch (e) {} try { const fromGql = await _afFetchImdbGraphQL(imdbId); if (fromGql && fromGql.rating) return fromGql; } catch (e) {} try { const fromLd = await _afFetchImdbLdJson(imdbId); if (fromLd && fromLd.rating) return fromLd; } catch (e) {} return null; })(); return _afImdbCache[imdbId]; } function _afScrapeImdbFromDom(imdbId) { const link = document.querySelector('[id^="block-"] a[href*="imdb.com/title/' + imdbId + '"]'); if (!link) return null; const box = link.closest('[id^="block-"]'); if (!box) return null; const text = (box.textContent || '').replace(/\s+/g, ' '); const m = text.match(/(\d{1,2}\.\d)/); if (!m) return null; const rating = parseFloat(m[1]); if (!(rating > 0 && rating <= 10)) return null; const vm = text.match(/([\d,]{3,})\s*(?:人|users|votes)/i); return { rating: rating, votes: vm ? vm[1].replace(/[^\d]/g, '') : '' }; } function _afFetchImdbGraphQL(imdbId) { return new Promise(function (resolve) { try { GM_xmlhttpRequest({ method: 'POST', url: 'https://api.graphql.imdb.com/', headers: { 'Content-Type': 'application/json' }, data: JSON.stringify({ query: 'query { title(id: "' + imdbId + '") { ratingsSummary { aggregateRating voteCount } } }' }), timeout: 8000, onload: function (res) { try { const s = JSON.parse(res.responseText).data.title.ratingsSummary; if (s && s.aggregateRating) resolve({ rating: s.aggregateRating, votes: s.voteCount || '' }); else resolve(null); } catch (e) { resolve(null); } }, onerror: function () { resolve(null); }, ontimeout: function () { resolve(null); } }); } catch (e) { resolve(null); } }); } function _afFetchImdbLdJson(imdbId) { return new Promise(function (resolve) { try { GM_xmlhttpRequest({ method: 'GET', url: 'https://www.imdb.com/title/' + imdbId + '/', headers: { 'User-Agent': navigator.userAgent, 'Accept-Language': 'en-US,en;q=0.9' }, timeout: 8000, onload: function (res) { try { const m = res.responseText.match(/"aggregateRating"\s*:\s*\{[^}]*?"ratingCount"\s*:\s*(\d+)[^}]*?"ratingValue"\s*:\s*([\d.]+)/) || res.responseText.match(/"aggregateRating"\s*:\s*\{[^}]*?"ratingValue"\s*:\s*([\d.]+)[^}]*?"ratingCount"\s*:\s*(\d+)/); if (!m) return resolve(null); if (String(m[1]).indexOf('.') > -1 && parseFloat(m[1]) <= 10) resolve({ rating: parseFloat(m[1]), votes: m[2] }); else resolve({ rating: parseFloat(m[2]), votes: m[1] }); } catch (e) { resolve(null); } }, onerror: function () { resolve(null); }, ontimeout: function () { resolve(null); } }); } catch (e) { resolve(null); } }); } // --- 5b. TMDB 评分获取(从 TMDB 影片页 LD+JSON 读取)--- const _afTmdbCache = {}; function _afGetTmdbScore(tmdbUrl) { if (!tmdbUrl) return Promise.resolve(null); if (_afTmdbCache[tmdbUrl] !== undefined) return _afTmdbCache[tmdbUrl]; _afTmdbCache[tmdbUrl] = (async function () { try { const fromLd = await _afFetchTmdbLdJson(tmdbUrl); if (fromLd && fromLd.rating) return fromLd; } catch (e) {} return null; })(); return _afTmdbCache[tmdbUrl]; } function _afFetchTmdbLdJson(tmdbUrl) { return new Promise(function (resolve) { try { GM_xmlhttpRequest({ method: 'GET', url: tmdbUrl, headers: { 'User-Agent': navigator.userAgent, 'Accept-Language': 'en-US,en;q=0.9' }, timeout: 8000, onload: function (res) { try { const ldMatch = res.responseText.match(/