在启用cookie的站点上使用urlretrieve的多线程Web scraper

Sim*_*ova 2 python cookies urllib urllib2 multiprocessing

我正在尝试编写我的第一个Python脚本,并且使用了大量的Google搜索,我认为我已经完成了.但是,我需要一些帮助才能让自己走完终点.

我需要编写一个脚本,登录到启用cookie的站点,刮掉一堆链接,然后生成一些进程来下载文件.我有程序在单线程中运行,所以我知道代码工作.但是,当我试图创建一个下载工作池时,我碰到了一堵墙.

#manager.py
import Fetch # the module name where worker lives
from multiprocessing import pool

def FetchReports(links,Username,Password,VendorID):
    pool = multiprocessing.Pool(processes=4, initializer=Fetch._ProcessStart, initargs=(SiteBase,DataPath,Username,Password,VendorID,))
    pool.map(Fetch.DownloadJob,links)
    pool.close()
    pool.join()


#worker.py
import mechanize
import atexit

def _ProcessStart(_SiteBase,_DataPath,User,Password,VendorID):
    Login(User,Password)

    global SiteBase
    SiteBase = _SiteBase

    global DataPath
    DataPath = _DataPath

    atexit.register(Logout)

def DownloadJob(link):
    mechanize.urlretrieve(mechanize.urljoin(SiteBase, link),filename=DataPath+'\\'+filename,data=data)
    return True
Run Code Online (Sandbox Code Playgroud)

在此修订版中,代码失败,因为cookie尚未传输给工作者以供urlretrieve使用.没问题,我能够用机械化的.cookiejar类保存cookies在经理,并传递给工人.

#worker.py
import mechanize
import atexit

from multiprocessing import current_process

def _ProcessStart(_SiteBase,_DataPath,User,Password,VendorID):
    global cookies
    cookies = mechanize.LWPCookieJar()

    opener = mechanize.build_opener(mechanize.HTTPCookieProcessor(cookies))

    Login(User,Password,opener)  # note I pass the opener to Login so it can catch the cookies.

    global SiteBase
    SiteBase = _SiteBase

    global DataPath
    DataPath = _DataPath

    cookies.save(DataPath+'\\'+current_process().name+'cookies.txt',True,True)

    atexit.register(Logout)

def DownloadJob(link):
    cj = mechanize.LWPCookieJar()
    cj.revert(filename=DataPath+'\\'+current_process().name+'cookies.txt', ignore_discard=True, ignore_expires=True)
    opener = mechanize.build_opener(mechanize.HTTPCookieProcessor(cj))

    file = open(DataPath+'\\'+filename, "wb")
    file.write(opener.open(mechanize.urljoin(SiteBase, link)).read())
    file.close
Run Code Online (Sandbox Code Playgroud)

但是,因为开启者(我认为)想要将二进制文件移回管理器进行处理而失败,并且我得到一个"无法解决对象"的错误消息,指的是它试图读取到该文件的网页.

显而易见的解决方案是从cookie罐中读取cookie并在发出urlretrieve请求时手动将它们添加到标题中,但我试图避免这种情况,这就是为什么我正在寻找建议.

jsa*_*nen 5

以正确的方式创建多线程Web scraper很难.我相信你能处理它,但为什么不使用已经完成的东西呢?

我真的建议你看看Scrapy http://scrapy.org/

它是一个非常灵活的开源Web scraper框架,可以处理您在这里需要的大部分内容.使用Scrapy,运行并发蜘蛛是一个配置问题,而不是编程问题(http://doc.scrapy.org/topics/settings.html#concurrent-requests-per-spider).您还将获得对cookie,代理,HTTP身份验证等的支持.

对我来说,在Scrapy中重写我的刮刀需要大约4个小时.所以请问问自己:你真的想自己解决线程问题,或者转向别人的肩膀,专注于网络抓取而不是线程问题?

PS.你现在正在使用机械化吗?请通过机械化常见问题解答http://wwwsearch.sourceforge.net/mechanize/faq.html注意这一点:

"它是线程安全的吗?

不.据我所知,您可以在线程代码中使用mechanize,但它不提供同步:您必须自己提供."

如果您真的想继续使用机械化,请开始阅读有关如何提供同步的文档.(例如http://effbot.org/zone/thread-synchronization.htm,http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm)