如何将URL列表批量保存为PDF?

时间:2019-07-15 20:15:57

标签: google-chrome pdf printing autohotkey

我有一个要保存为PDF的食谱的URL列表,然后我对该站点的订阅用尽了。使用Xenu Link Sleuth收集URL,将其保存到Excel电子表格中,进行调整以进行清理,删除重复项并导出到以Tab分隔的txt文件中。

一个朋友编写了一个AutoHotKey脚本,该脚本将使用URL并在Chrome中使用“打印为PDF”选项,但这存在问题。除了由于脚本需要控制鼠标而使我的计算机无法运行之外,它经常通过某种方式尝试保存两次相同的URL(即使没有重复的链接)或只是不保存任何内容而无法正常工作。

下面是我朋友写的脚本。这似乎对他最有效,但对我来说,在这种状态下将不会保存任何东西。在Sleep 7000之后,我添加了另一个Send {Enter},以便激活另存为对话框中用于保存PDF的Save按钮以及另一个较短的Sleep。

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

Loop, read, %A_ScriptDir%\CookSpread.txt

{
StringSplit, LineArray, A_LoopReadLine, %A_Tab%
  URL := LineArray1

Run, %URL%

Sleep 7000

Click 3407, 241
Sleep 3000
Send {Enter}
Sleep 7000

Send ^{F4}
Sleep 4000
}

我做了一些修改。一个是我减少了每个步骤之间的时间(也许是问题所在)。我还添加了单击以选择要与配方一起打印的营养信息。您也可以在结尾处看到我的第二个Enter。

Sleep 6000
Click 1500, 550
Sleep 500
Click 1480, 220
Sleep 3000
Send {Enter}
Sleep 1000
Send {Enter}
Sleep 1000
Send ^{F4}
Sleep 2000
}

我希望它能正常运行,从文本文件中获取链接,在浏览器中将其打开,将鼠标移到打印按钮(单击)上,这将打开“打印”界面。然后按Enter键单击“保存”按钮,然后按Enter键单击“保存”按钮,保存文件,然后关闭当前的Chrome选项卡,然后重新开始。

发生的事情是,它适合20个或30个URL,但是随后在保存时发生了什么,这表示该文件已经存在,并询问我是否要覆盖它。在脚本继续尝试执行其余步骤的同时,此窗口保持打开状态,因此其他任何事情都不会完成。最终发生的事情是打开了数百个选项卡,因为URL仍在浏览器中打开。

我想知道是否有人知道如何纠正此问题,或者他们是否知道另一种方法来完成此操作。一个独立的GUI应用程序或可以在后台使用我的登录凭据的东西是理想的选择,因为AutoHotKey脚本使我的计算机在运行时无法使用。但是,如果有人能弄清楚如何进行这项工作,那对我来说已经足够了。

1 个答案:

答案 0 :(得分:1)

尝试:

全部替换

此代码中的

D:\ Downloads ” 带有文件夹路径的程序将保存打印的URL

打印设置中,“ 目标”必须为“ 另存为PDF

#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%

ModernBrowsers := "Chrome_WidgetWin_0,Chrome_WidgetWin_1,MozillaWindowClass"
LegacyBrowsers := "IEFrame,OperaWindowClass"

FileCreateDir, D:\Downloads\Newly created
FileMove, D:\Downloads\*.pdf, D:\Downloads\Newly created\, 1

F1::
If !WinExist("ahk_exe chrome.exe")
    Run, chrome.exe
WinWait, ahk_exe chrome.exe
Sleep, 500
Loop, read, %A_ScriptDir%\CookSpread.txt
{
    StringSplit, LineArray, A_LoopReadLine, %A_Tab%
    URL := LineArray1
    Run, chrome.exe "%URL%"
    Sleep, 500
    Loop
    {
        WinActivate, ahk_exe chrome.exe
        WinWaitActive, ahk_exe chrome.exe, , 1
        If !(ErrorLevel)
             break
    }
    Loop
    {
        OutputURL := GetActiveBrowserURL()
        Sleep, 500
        If (OutputURL = "")
             continue
        If (OutputURL = URL)
            break
    }
    Sleep, 500    
    Loop
    {
        WinActivate, ahk_exe chrome.exe
        WinWaitActive, ahk_exe chrome.exe, , 1
        If !(ErrorLevel)
             break
    }
    Send, ^p
    Sleep, 500    
    Loop
    {
        WinActivate, ahk_exe chrome.exe
        WinWaitActive, ahk_exe chrome.exe, , 1
        If !(ErrorLevel)
             break
    }
    Sleep, 300
    Send, {Enter}
    Sleep, 500
    WinWait, Save As ahk_exe chrome.exe   
    Loop
    {
        WinActivate, Save As ahk_exe chrome.exe
        WinWaitActive, Save As ahk_exe chrome.exe, , 1
        If !(ErrorLevel)
        {
             Send, !s
             break
        }
    }
    Sleep, 500
    Loop
    {
        FileMove, D:\Downloads\*.pdf, D:\Downloads\Newly created\, 1
        Sleep, 500
        If !FileExist("D:\Downloads\*.pdf")
        {
            WinActivate, ahk_exe chrome.exe
            WinWaitActive, ahk_exe chrome.exe, , 1
            If !(ErrorLevel)
            {           
                Send, ^w
                break 
            } 
        }   
    }
    Sleep, 500
}
Run D:\Downloads\Newly created
return


; https://www.autohotkey.com/boards/viewtopic.php?t=3702
; Get the URL of the current (active) browser tab

GetActiveBrowserURL(){
    global ModernBrowsers, LegacyBrowsers
    WinGetClass, sClass, A
    If sClass In % ModernBrowsers   ; %
        Return GetBrowserURL_ACC(sClass)
    Else If sClass In % LegacyBrowsers  ; %
        Return GetBrowserURL_DDE(sClass) ; empty string if DDE not supported (or not a browser)
    Else
        Return ""
}

; "GetBrowserURL_DDE" adapted from DDE code by Sean, (AHK_L version by maraskan_user)
; Found at 
; http://autohotkey.com/board/topic/17633-/?p=434518

GetBrowserURL_DDE(sClass) {
    WinGet, sServer, ProcessName, % "ahk_class " sClass     ; %
    StringTrimRight, sServer, sServer, 4
    iCodePage := A_IsUnicode ? 0x04B0 : 0x03EC ; 0x04B0 = CP_WINUNICODE, 0x03EC = CP_WINANSI
    DllCall("DdeInitialize", "UPtrP", idInst, "Uint", 0, "Uint", 0, "Uint", 0)
    hServer := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", sServer, "int", iCodePage)
    hTopic := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", "WWW_GetWindowInfo", "int", iCodePage)
    hItem := DllCall("DdeCreateStringHandle", "UPtr", idInst, "Str", "0xFFFFFFFF", "int", iCodePage)
    hConv := DllCall("DdeConnect", "UPtr", idInst, "UPtr", hServer, "UPtr", hTopic, "Uint", 0)
    hData := DllCall("DdeClientTransaction", "Uint", 0, "Uint", 0, "UPtr", hConv, "UPtr", hItem, "UInt", 1, "Uint", 0x20B0, "Uint", 10000, "UPtrP", nResult) ; 0x20B0 = XTYP_REQUEST, 10000 = 10s timeout
    sData := DllCall("DdeAccessData", "Uint", hData, "Uint", 0, "Str")
    DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hServer)
    DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hTopic)
    DllCall("DdeFreeStringHandle", "UPtr", idInst, "UPtr", hItem)
    DllCall("DdeUnaccessData", "UPtr", hData)
    DllCall("DdeFreeDataHandle", "UPtr", hData)
    DllCall("DdeDisconnect", "UPtr", hConv)
    DllCall("DdeUninitialize", "UPtr", idInst)
    csvWindowInfo := StrGet(&sData, "CP0")
    StringSplit, sWindowInfo, csvWindowInfo, `" ;"; comment to avoid a syntax highlighting issue in autohotkey.com/boards
    Return sWindowInfo2
}

GetBrowserURL_ACC(sClass) {
    global nWindow, accAddressBar
    If (nWindow != WinExist("ahk_class " sClass)) ; reuses accAddressBar if it's the same window
    {
        nWindow := WinExist("ahk_class " sClass)
        accAddressBar := GetAddressBar(Acc_ObjectFromWindow(nWindow))
    }
    Try sURL := accAddressBar.accValue(0)
    If (sURL == "") {
        WinGet, nWindows, List, % "ahk_class " sClass ; ; % In case of a nested browser window as in the old CoolNovo (TO DO: check if still needed)
        If (nWindows > 1) {
            accAddressBar := GetAddressBar(Acc_ObjectFromWindow(nWindows2))
            Try sURL := accAddressBar.accValue(0)
        }
    }
    If ((sURL != "") and (SubStr(sURL, 1, 4) != "http")) ; Modern browsers omit "http://"
        sURL := "http://" sURL
    If (sURL == "")
        nWindow := -1 ; Don't remember the window if there is no URL
    Return sURL
}

; "GetAddressBar" based in code by uname
; Found at http://autohotkey.com/board/topic/103178-/?p=637687

GetAddressBar(accObj) {
    Try If ((accObj.accRole(0) == 42) and IsURL(accObj.accValue(0)))
        Return accObj
    Try If ((accObj.accRole(0) == 42) and IsURL("http://" accObj.accValue(0))) ; Modern browsers omit "http://"
        Return accObj
    For nChild, accChild in Acc_Children(accObj)
        If IsObject(accAddressBar := GetAddressBar(accChild))
            Return accAddressBar
}

IsURL(sURL) {
    Return RegExMatch(sURL, "^(?<Protocol>https?|ftp)://(?<Domain>(?:[\w-]+\.)+\w\w+)(?::(?<Port>\d+))?/?(?<Path>(?:[^:/?# ]*/?)+)(?:\?(?<Query>[^#]+)?)?(?:\#(?<Hash>.+)?)?$")
}

; The code below is part of the Acc.ahk Standard Library by Sean (updated by jethrow)
; Found at http://autohotkey.com/board/topic/77303-/?p=491516

Acc_Init()
{
    static h
    If Not h
        h:=DllCall("LoadLibrary","Str","oleacc","Ptr")
}
Acc_ObjectFromWindow(hWnd, idObject = 0)
{
    Acc_Init()
    If DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc)=0
    Return ComObjEnwrap(9,pacc,1)
}
Acc_Query(Acc) {
    Try Return ComObj(9, ComObjQuery(Acc,"{618736e0-3c3d-11cf-810c-00aa00389b71}"), 1)
}
Acc_Children(Acc) {
    If ComObjType(Acc,"Name") != "IAccessible"
        ErrorLevel := "Invalid IAccessible Object"
    Else {
        Acc_Init(), cChildren:=Acc.accChildCount, Children:=[]
        If DllCall("oleacc\AccessibleChildren", "Ptr",ComObjValue(Acc), "Int",0, "Int",cChildren, "Ptr",VarSetCapacity(varChildren,cChildren*(8+2*A_PtrSize),0)*0+&varChildren, "Int*",cChildren)=0 {
            Loop %cChildren%
                i:=(A_Index-1)*(A_PtrSize*2+8)+8, child:=NumGet(varChildren,i), Children.Insert(NumGet(varChildren,i-8)=9?Acc_Query(child):child), NumGet(varChildren,i-8)=9?ObjRelease(child):
            Return Children.MaxIndex()?Children:
        } Else
            ErrorLevel := "AccessibleChildren DllCall Failed"
    }
}