python - 在启用 cookie 的站点上使用 urlretrieve 的多线程网络抓取工具

标签 python cookies urllib2 multiprocessing urllib

我正在尝试编写我的第一个 Python 脚本,并且通过大量谷歌搜索,我认为我即将完成。但是,我需要一些帮助才能冲过终点线。

我需要编写一个脚本来登录启用 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

在此版本中,代码失败,因为 cookie 尚未传输给 worker 以供 urlretrieve 使用。没问题,我能够使用 mechanize 的 .cookiejar 类将 cookie 保存在管理器中,并将它们传递给工作人员。

#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

但是,这失败了,因为 opener(我认为)想要将二进制文件移回管理器进行处理,并且我收到“无法腌制对象”错误消息,指的是它试图读取文件的网页.

明显的解决方案是从 cookie jar 中读取 cookie 并在发出 urlretrieve 请求时手动将它们添加到 header ,但我试图避免这种情况,这就是我寻求建议的原因。

最佳答案

以正确的方式创建多线程网络抓取工具很困难。我相信您可以处理它,但为什么不使用已经完成的事情呢?

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

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

对我来说,用 Scrapy 重写我的爬虫花了大约 4 个小时。所以请问问自己:你真的想自己解决线程问题,还是站在别人的肩膀上,专注于网络抓取问题,而不是线程问题?

附言。你现在在用机械化吗?请从 mechanize FAQ http://wwwsearch.sourceforge.net/mechanize/faq.html 中注意到这一点:

“它是线程安全的吗?

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

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

关于python - 在启用 cookie 的站点上使用 urlretrieve 的多线程网络抓取工具,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6111372/

相关文章:

python - 有没有一种方法可以处理 Blob 存储中的 PDF 文件,而无需使用 Python 将它们下载到本地?

python - Python 中的条件最近邻

php - 使用 php 为子域设置 cookie 不起作用

Python Mechanize 检查服务器是否可用

python - 将 curl 翻译成 python urllib2

python - 使用 Python 跟踪重定向和 cookie

python - 检查对象是否为列表的 pythonic 方法是什么?

python - python + Google 应用引擎中的自动完成文本框示例

php - Cookie 嗅探器 - PHP

c# - 使用 cookie 身份验证的 ASP.NET Core 2.0 自定义中间件