【发布时间】:2020-11-07 00:12:39
【问题描述】:
我有一个我无法开发逻辑的用例。将其浮动在这里以征求专家的建议。
快速上下文:
我有一个包含 2,500 个 URL 的列表。我可以使用 Python 和 Selenium 依次抓取它们。
1,000 个 URL 的运行时间约为 1.5 小时
我想要达到的目标:
我正在尝试通过并行执行来优化运行时间。我已经查看了有关堆栈溢出的各种帖子。不知何故,我无法找到拼图的缺失部分。
详情
-
我需要重用驱动程序,而不是为每个 URL 关闭并重新打开它们。我遇到了一个利用 threading.local() 的帖子Python selenium multiprocessing。如果我重新运行相同的代码,以某种方式打开的驱动程序数量超过了指定的线程数量
-
请注意,该网站要求用户使用用户名和密码登录。我的目标是第一次启动驱动程序(比如 5 个驱动程序)并登录。我想继续为所有未来的 URL 重复使用相同的驱动程序,而不必关闭驱动程序并再次登录
-
另外,我是 Selenium 网络抓取的新手。只是熟悉基础知识。多线程是未知领域。非常感谢您的帮助
在下面分享我的代码sn-p:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import pandas as pd
from multiprocessing.dummy import Pool as ThreadPool
threadLocal = threading.local()
# Function to open web driver
def get_driver():
options = Options()
driver = webdriver.Chrome(<Location to chrome driver>, options = options)
return driver
# Function to login to website & scrape from website
def parse_url(url):
driver = get_driver()
login_url = "https://..."
driver.get(login_url)
# Enter user ID
# Enter password
# Click on Login button
# Open web page of interest & scrape
driver.get(url)
htmltext = driver.page_source
htmltext1 = htmltext[0:100]
return [url, htmltext1]
# Function for multi-threading
def main():
urls = ["url1",
"url2",
"url3",
"url4"]
pool = ThreadPool(2)
records = pool.map(parse_url, urls)
pool.close()
pool.join()
return records
if __name__ =="__main__":
result = pd.DataFrame(columns = ["url", "html_text"], data = main())
如何修改上面的代码:
- 我最终重用了我的驱动程序
- 只登录一次网站并同时抓取多个网址
【问题讨论】:
-
嗨伙计 - 好问题 - 我不认为重用打开的浏览器是最好的解决方案。我认为当您一次打开 5 个时会增加一定程度的复杂性。作为替代方案,您的站点如何进行身份验证? - 如果是 cookie,您可以登录一次,使用 get_cookies 将会话存储在变量中,然后启动 5x 并行执行 - 每次获得新浏览器时,从您的商店设置 cookie .这可能意味着不再登录并直接导航到您的目标网址
-
您找到解决方案了吗?如果是的话,你能分享一下吗?谢谢!
标签: python python-3.x multithreading selenium web-scraping