我正在尝试编写我的第一个 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/