又一软件开发商面临破产,背后原因尽然是这个

本文介绍了如何使用Python通过模拟网站接口实现PDF到WORD的转换。作者首先分析了转换思路,然后展示了利用requests库进行POST请求的代码实现,强调该方法适用于测试接口,完整功能需使用原版服务。

想必小伙伴都经历过,当你想要把PDF转为WORD时,页面上就会出现四个字甩在你眼前:

不充钱就想白嫖??想得美~不能这样说,咱们是资源合理利用,今天用python写一个PDF转WORD的小工具(基于某网站接口)。

一、思路分析

网上一搜,你可以发现很多PDF转换的工具,其中不乏在线转换的网站,比如这样的:

那么,通过网站提供的测试接口,我们便可以通过爬虫模拟的方式实现转换。

通过抓包分析,知道这是一个POST请求,接下来用requests库模拟即可。
需要注意的是,这个接口仅用于测试,所以可供转换的页面等都有所限制,如需更完整的功能还请支持原版。

二、我的代码

正所谓一万个coders,就有一万种codes,以下为我的代码,仅供参考。
导入相关库:

import time
import requests

定义PDF2Word类:

class PDF2Word():
    def __init__(self):
        self.machineid = 'ccc052ee5200088b92342303c4ea9399'
        self.token = ''
        self.guid = ''
        self.keytag = ''
    
    def produceToken(self):
        url = 'https://app.xunjiepdf.com/api/producetoken'
        headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0',
                'Accept': 'application/json, text/javascript, */*; q=0.01',
                'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'X-Requested-With': 'XMLHttpRequest',
                'Origin': 'https://app.xunjiepdf.com',
                'Connection': 'keep-alive',
                'Referer': 'https://app.xunjiepdf.com/pdf2word/',}
        data = {'machineid':self.machineid}
        res = requests.post(url,headers=headers,data=data)
        res_json = res.json()
        if res_json['code'] == 10000:
            self.token = res_json['token']
            self.guid = res_json['guid']
            print('成功获取token')
            return True
        else:
            return False
    
    def uploadPDF(self,filepath):
        filename = filepath.split('/')[-1]
        files = {'file': open(filepath,'rb')}
        url = 'https://app.xunjiepdf.com/api/Upload'
        headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0',
                'Accept': '*/*',
                'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
                'Content-Type': 'application/pdf',
                'Origin': 'https://app.xunjiepdf.com',
                'Connection': 'keep-alive',
                'Referer': 'https://app.xunjiepdf.com/pdf2word/',}
        params = (
                ('tasktype', 'pdf2word'),
                ('phonenumber', ''),
                ('loginkey', ''),
                ('machineid', self.machineid),
                ('token', self.token),
                ('limitsize', '2048'),
                ('pdfname', filename),
                ('queuekey', self.guid),
                ('uploadtime', ''),
                ('filecount', '1'),
                ('fileindex', '1'),
                ('pagerange', 'all'),
                ('picturequality', ''),
                ('outputfileextension', 'docx'),
                ('picturerotate', '0,undefined'),
                ('filesequence', '0,undefined'),
                ('filepwd', ''),
                ('iconsize', ''),
                ('picturetoonepdf', ''),
                ('isshare', '0'),
                ('softname', 'pdfonlineconverter'),
                ('softversion', 'V5.0'),
                ('validpagescount', '20'),
                ('limituse', '1'),
                ('filespwdlist', ''),
                ('fileCountwater', '1'),
                ('languagefrom', ''),
                ('languageto', ''),
                ('cadverchose', ''),
                ('pictureforecolor', ''),
                ('picturebackcolor', ''),
                ('id', 'WU_FILE_1'),
                ('name', filename),
                ('type', 'application/pdf'),
                ('lastModifiedDate', ''),
                ('size', ''),)
        res= requests.post(url,headers=headers,params=params,files=files)
        res_json = res.json()
        if res_json['message'] == '上传成功':
            self.keytag = res_json['keytag']
            print('成功上传PDF')
            return True
        else:
            return False
        
    def progress(self):
        url = 'https://app.xunjiepdf.com/api/Progress'
        headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0',
                'Accept': 'text/plain, */*; q=0.01',
                'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'X-Requested-With': 'XMLHttpRequest',
                'Origin': 'https://app.xunjiepdf.com',
                'Connection': 'keep-alive',
                'Referer': 'https://app.xunjiepdf.com/pdf2word/',}
        data = {
              'tasktag': self.keytag,
              'phonenumber': '',
              'loginkey': '',
              'limituse': '1'}
        res= requests.post(url,headers=headers,data=data)
        res_json = res.json()
        if res_json['message'] == '处理成功':
            print('PDF处理完成')
            return True
        else:
            print('PDF处理中')
            return False
        
    def downloadWord(self,output):
        url = 'https://app.xunjiepdf.com/download/fileid/%s'%self.keytag
        res = requests.get(url)
        with open(output,'wb') as f:
            f.write(res.content)
            print('PDF下载成功("%s")'%output)
            
    def convertPDF(self,filepath,outpath):
        filename = filepath.split('/')[-1]
        filename = filename.split('.')[0]+'.docx'
        self.produceToken()
        self.uploadPDF(filepath)
        while True:
            res = self.progress()
            if res == True:
                break
            time.sleep(1)
        self.downloadWord(outpath+filename)

执行主函数:

 
if __name__=='__main__':    
    pdf2word = PDF2Word()
    pdf2word.convertPDF('001.pdf','')

注意:convertPDF函数有两个参数,第一个为需要转换的PDF,第二个参数为转换后的目录。
run一下,一键入魂,".docx"文件已经躺在了我的目录中,舒服了~

 

<think>我们正在为《饥荒》开发个MOD,目标是为所有生物添加个额外掉落物。 根据饥荒MOD开发知识,我们可以通过修改生物(Prefab)的死亡回调函数来添加额外掉落。 通常,生物在死亡时会调用个函数(如:inst.components.lootdropper:AddChanceLoot() 或直接设置loot表),我们可以通过劫持或修改这个函数来添加额外掉落。 但是,由于“所有生物”种类繁多,我们可能需要个全局的方式来处理,而不是逐修改每个生物的Prefab文件。 我们可以考虑在游戏初始化时,遍历所有Prefab,如果该Prefab有lootdropper组件,则修改其生成掉落物的函数(例如,在原有函数执行后添加额外掉落)。 然而,需要注意的是,有些生物可能没有lootdropper组件(比如些不会死亡的生物),或者有些生物有特殊的掉落生成逻辑。因此,我们需要谨慎处理。 步骤: 1. 在modmain.lua中,我们可以使用AddPrefabPostInitAny(任意Prefab初始化后的回调)来遍历所有Prefab。 2. 在回调中,我们检查该Prefab是否有lootdropper组件。如果有,我们保存原有的生成掉落函数,然后替换为个新的函数,这个新函数先调用原有函数,然后再添加我们的额外掉落物。 但是,注意:AddPrefabPostInitAny可能会对性能有影响,因为它会为每个Prefab都执行次。因此,我们需要确保只对需要修改的Prefab(即那些有lootdropper组件的)进行操作。 另种更高效的方法是使用AddComponentPostInit,但是它是针对组件的,所以我们可以只对lootdropper组件进行修改。这样,只要个Prefab有lootdropper组件,我们就会修改它的行为。 我们选择第二种方法:修改lootdropper组件。 具体思路: 在lootdropper组件初始化后,我们劫持它的生成掉落函数(通常为GenerateLoot),在生成原有掉落之后,再添加我们的额外掉落物。 注意:GenerateLoot函数在生成掉落时会被调用,它负责根据loot表生成实际掉落的物品。 我们可以这样做: 1. 保存原有的GenerateLoot函数 2. 创建个新的GenerateLoot函数,它先调用原函数,然后添加额外掉落。 但是,额外掉落物是什么?我们可以定义个额外的掉落表,例如,我们想要每个生物都额外掉落个“噩梦燃料”(当然,这只是个例子,具体掉落什么可以根据需要设定)。 为了灵活性,我们可以设置个配置选项,让玩家可以自定义额外掉落的物品和概率。 但是,由于问题中要求为所有生物添加额外掉落物,我们假设额外掉落物是固定的(比如个mod物品),并且100%掉落。 实现: 在modmain.lua中: 首先,定义个函数,用于修改lootdropper组件。这个函数会在每个lootdropper组件初始化后被调用。 然后,在这个函数中,我们替换掉GenerateLoot方法。 代码框架如下: ```lua -- 引入必要的GLOBAL变量 local Lootdropper = GLOBAL.require("components/lootdropper") -- 保存原有的GenerateLoot函数 local old_GenerateLoot = Lootdropper.GenerateLoot -- 新的GenerateLoot函数 function Lootdropper:GenerateLoot(...) -- 先调用原函数生成原有的掉落 old_GenerateLoot(self, ...) -- 然后添加我们的额外掉落 -- 假设我们额外掉落的物品是"nightmarefuel",并且每次掉落1个 -- 注意:我们需要检查当前是否在服务器上(因为掉落物品是服务器行为) if GLOBAL.TheWorld.ismastersim then -- 在原有掉落物品的基础上添加 -- 注意:self.loot是个表,存放了这次掉落的所有物品 table.insert(self.loot, "nightmarefuel") end end ``` 但是,上述代码有几个问题: 1. 它修改了所有lootdropper组件的GenerateLoot函数,包括那些我们不想修改的生物(比如玩家死亡后的lootdropper?)。我们需要判断这个lootdropper属于哪个Prefab,然后决定是否添加额外掉落。或者,我们可以判断这个lootdropper的拥有者(inst)是否是生物(即是否有health组件?),但这样也不完全准确。 2. 我们可能并不希望所有有lootdropper组件的Prefab都掉落额外物品(比如箱子、容器等也会使用lootdropper组件)。因此,我们需要判断这个Prefab是否是个“生物”。 如何判断个Prefab是生物?我们可以检查它是否有health组件,因为生物通常都有health组件。但是,有些非生物也可能有health组件(比如某些可破坏的物体)。所以,我们可以结合其他条件,比如检查它是否有combat组件(因为生物通常可以战斗)?但这也不绝对。 另种思路:我们只修改那些在生物Prefab上使用的lootdropper组件。但是,由于我们无法预知所有生物,所以我们可以通过标签(tags)来判断。饥荒中的生物通常有“character”标签?或者“monster”标签?但也不尽然。 因此,我们可以采用个更通用的方法:为所有有health组件且health组件不为0(即不是死亡状态)的实体添加额外掉落。但是,在GenerateLoot被调用时,实体可能已经死亡,health组件可能已经被移除?所以这也不可靠。 考虑到这些,我们可以这样处理:在GenerateLoot函数中,我们判断这个lootdropper的拥有者(inst)是否有“_is_creature”这样的标记?但是,我们如何标记呢? 我们可以在Prefab初始化的时候,给生物打上标记。但是这样我们又回到了需要遍历Prefab的问题。 因此,我们可以折中:在GenerateLoot函数中,我们检查inst是否有health组件(即使死亡,组件可能还在,只是被禁用?),或者检查inst:HasTag("character")或inst:HasTag("monster")?但这样可能会漏掉些生物。 为了简单起见,我们假设所有有health组件并且不是玩家的实体都是生物。因为玩家死亡也会调用lootdropper,但我们可能不想给玩家添加额外掉落。 修改后的代码: ```lua local Lootdropper = GLOBAL.require("components/lootdropper") local old_GenerateLoot = Lootdropper.GenerateLoot function Lootdropper:GenerateLoot(...) old_GenerateLoot(self, ...) if GLOBAL.TheWorld.ismastersim then local inst = self.inst -- 检查inst是否有health组件,并且不是玩家 if inst.components.health and not inst:HasTag("player") then table.insert(self.loot, "nightmarefuel") end end end ``` 但是,注意:有些生物可能有多个掉落物,而GenerateLoot函数可能会被多次调用(例如,有些生物会多次调用GenerateLoot来生成多组掉落)?这不太可能,因为GenerateLoot通常只会在死亡时调用次。但是,我们插入的额外掉落物可能会在每次调用GenerateLoot时都被添加次。所以,如果GenerateLoot被多次调用,那么就会添加多次额外掉落。这通常不会发生,因为死亡事件只触发次掉落生成。 另外,我们插入的是个物品名称字符串,但lootdropper在生成实际物品时,会根据这个字符串生成Prefab。所以,我们需要确保"nightmarefuel"是个有效的Prefab名称。 但是,我们可能希望这个额外掉落物是可配置的,并且可能不是100%掉落。我们可以修改为: ```lua if inst.components.health and not inst:HasTag("player") then if math.random() < 0.5 then -- 50%的几率 table.insert(self.loot, "nightmarefuel") end end ``` 或者,我们可以让额外掉落物和数量可以配置。为了灵活性,我们可以创建个配置表,然后在modmain.lua中读取配置。 但是,由于问题要求是“为所有生物添加个额外掉落物”,我们暂时按照100%掉落个固定物品来实现。 然而,上述方法有个潜在的缺陷:它修改了全局的Lootdropper组件,这可能会与其他修改同个组件的mod冲突。因此,我们需要在文档中说明。 另外,我们也可以使用AddComponentPostInit来修改特定实例的组件,但是这里我们修改的是组件的类,所以会影响到所有实例。 另种更安全的方法是:我们只修改我们想要修改的生物的Prefab,通过AddPrefabPostInit来为每个生物添加个自定义的死亡事件处理函数。但是,这样我们需要遍历所有生物,而饥荒中的生物Prefab非常多,而且有些mod添加的生物我们可能无法全部覆盖。 因此,我们选择修改组件的方法,因为它可以覆盖所有生物(包括mod添加的生物,只要它们使用了lootdropper组件)。 最后,我们还需要考虑:如果某个生物原本没有lootdropper组件,我们就无法修改。但是,饥荒中几乎所有的生物都有lootdropper组件,因为这是负责掉落的核心组件。 所以,我们在modmain.lua中写入以下代码: ```lua -- 在mod初始化时执行 AddComponentPostInit("lootdropper", function(self) -- 保存原有的GenerateLoot local old_GenerateLoot = self.GenerateLoot -- 覆盖GenerateLoot function self:GenerateLoot(...) old_GenerateLoot(self, ...) if GLOBAL.TheWorld.ismastersim then local inst = self.inst if inst.components.health and not inst:HasTag("player") then table.insert(self.loot, "nightmarefuel") end end end end) ``` 但是,注意:AddComponentPostInit是在组件被实例化时调用的,所以每个lootdropper组件实例都会有自己的GenerateLoot函数(通过闭包保存了old_GenerateLoot)。这样可能会稍微增加内存占用,但通常可以接受。 另外,我们也可以修改组件的元表(metatable)来替换GenerateLoot函数,这样所有实例共享同个函数。但是,由于每个实例的old_GenerateLoot可能不同(因为不同的Prefab可能有不同的GenerateLoot函数),所以不能简单地用个全局函数替换。 因此,我们采用上述方法:为每个lootdropper组件实例替换GenerateLoot函数。 但是,我们还需要注意:个Prefab可能有多个lootdropper组件实例吗?通常,个实体只有个lootdropper组件。 最后,我们还需要考虑兼容性:如果其他mod也修改了GenerateLoot函数,那么我们的修改可能会覆盖其他mod,或者被覆盖。为了避免这种情况,我们可以使用更高级的劫持技术,比如在old_GenerateLoot中保存的是当前GenerateLoot函数,然后我们替换为个新的函数,这样如果其他mod也这样做,就会形成调用链。 但是,由于饥荒mod社区没有统的标准,我们只能尽量保证兼容性。 因此,我们使用个更安全的方法:将old_GenerateLoot保存在组件实例上,然后调用它,这样如果其他mod也做了类似的事情,那么我们的old_GenerateLoot可能是已经被其他mod修改过的函数。 所以,我们上面的代码已经可以形成调用链:先调用原来的(可能是其他mod修改过的)GenerateLoot,然后再添加我们的额外掉落。 这样,如果多个mod都采用这种方式,那么就会依次执行。 但是,如果其他mod在GenerateLoot函数中修改了self.loot,那么我们的额外掉落会添加在最后。 综上所述,我们使用AddComponentPostInit方法来修改lootdropper组件,为所有非玩家的生物添加额外掉落物。 注意:在实际开发中,我们可能需要让额外掉落物可配置,并且避免硬编码。这里为了示例,我们使用"nightmarefuel"。 另外,我们还需要考虑:如果生物原本的掉落表(self.loot)是nil怎么办?所以,我们应该先确保self.loot是个表。 修改后的代码: ```lua AddComponentPostInit("lootdropper", function(self) local old_GenerateLoot = self.GenerateLoot function self:GenerateLoot(...) old_GenerateLoot(self, ...) if GLOBAL.TheWorld.ismastersim then local inst = self.inst -- 确保loot是个表 if self.loot == nil then self.loot = {} end if inst.components.health and not inst:HasTag("player") then table.insert(self.loot, "nightmarefuel") end end end end) ``` 这样,即使原本没有掉落,我们也会创建个空表,并添加额外掉落。 最后,我们还需要注意:GenerateLoot函数可能有返回值?查看饥荒源代码,GenerateLoot函数没有返回值。所以,我们不需要处理返回值。 因此,我们完成了为所有生物添加额外掉落物的mod代码。 注意:这个mod可能会影响游戏平衡,请玩家酌情使用。 相关问题: 1. 如何让这个额外掉落物可以配置(比如通过mod配置界面)? 2. 如何避免给某些特定的生物添加额外掉落物(比如boss)? 3. 如果我想让额外掉落物有多种可能(比如随机从几种物品中选种),如何实现? 4. 如何让额外掉落物的数量也是随机的? 5. 如果我想根据生物的类型(比如敌对生物、中立生物)来掉落不同的物品,如何实现? 请根据上述问题,生成相关问题。</think>### 饥荒 MOD 开发:为所有生物添加额外掉落物 在《饥荒》MOD 开发中,为所有生物添加额外掉落物需要修改生物死亡时的掉落逻辑。以下是具体实现步骤: #### 核心实现代码(在 `modmain.lua` 中) ```lua -- 劫持生物死亡时的掉落生成函数 AddComponentPostInit("lootdropper", function(self) local _oldSetLoot = self.SetLoot self.SetLoot = function(lootdropper, loot) _oldSetLoot(lootdropper, loot) -- 保留原始掉落 -- 添加额外掉落物(例如:噩梦燃料) if lootdropper.inst:HasTag("monster") then -- 仅限怪物 lootdropper:AddChanceLoot("nightmarefuel", 0.5) -- 50% 概率掉落 else -- 其他生物 lootdropper:AddChanceLoot("seeds", 0.8) -- 80% 概率掉落种子 end end end) ``` #### 关键代码解析 1. **劫持掉落组件** `AddComponentPostInit("lootdropper")` 在所有生物初始化时修改掉落组件[^4]。 2. **添加额外掉落** - `AddChanceLoot("item_name", probability)`:添加概率掉落物 - 示例: ```lua lootdropper:AddChanceLoot("goldnugget", 0.3) -- 30% 概率掉落金块 ``` 3. **生物分类处理** 通过标签系统区分生物类型: ```lua if inst:HasTag("monster") then -- 怪物类 if inst:HasTag("smallcreature") then -- 小动物类 ``` #### 配置额外掉落物 在 `modinfo.lua` 中添加配置选项: ```lua configuration_options = { { name = "EXTRA_LOOT_ITEM", label = "额外掉落物", options = { {description = "噩梦燃料", data = "nightmarefuel"}, {description = "金块", data = "goldnugget"}, {description = "种子", data = "seeds"} }, default = "seeds" }, { name = "DROP_CHANCE", label = "掉落概率", options = { {description = "30%", data = 0.3}, {description = "50%", data = 0.5}, {description = "80%", data = 0.8} }, default = 0.5 } } ``` #### 注意事项 1. **避免影响玩家** 添加过滤条件排除玩家角色: ```lua if not lootdropper.inst:HasTag("player") then -- 添加额外掉落 end ``` 2. **特殊生物处理** 对 BOSS 类生物单独设置: ```lua if inst:HasTag("epic") then -- BOSS 生物 lootdropper:AddChanceLoot("deerclops_eyeball", 1.0) -- 100% 掉落眼球 end ``` 3. **兼容性建议** 使用 `GLOBAL.package.loaded` 检查其他 MOD 的兼容性: ```lua if GLOBAL.package.loaded["workshop-123456"] then -- 特定 MOD 兼容代码 end ``` --- ### 相关问题 1. **如何让额外掉落物只对特定生物生效**? (例如:仅限蜘蛛或猪人掉落特殊物品) 2. **如何实现多层掉落概率**? (例如:先有 50% 概率掉落包裹,包裹内再随机开出土著或宝石) 3. **MOD 添加新生物时如何自动继承额外掉落机制**? (无需手动配置新生物的掉落表) 4. **如何让额外掉落物受角色幸运值影响**? (例如:薇洛的幸运值提高掉落概率) 5. **如何避免与其它修改掉落系统的 MOD 冲突**? (兼容性处理的最佳实践) [^1]: 引用自饥荒联机版MOD-杀生丸特性说明 [^4]: 引用自进程与资源管理概念说明
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值