我确实有一个副业项目,我发现它非常具有挑战性,同时也非常有趣。
所以!想法很简单!
使用 Selenium!
登录 Linkedln!
转到带有您的参数的搜索链接 - 在我的例子中是技术。招聘人员。
每页有 10 个按钮。按钮的状态为“连接”、“关注”或“消息”
目标是每次我检查按钮时,如果它是“连接”或“关注”,我们就想单击它。
如果是“连接”,还添加一条自定义消息。
当我们完成 10 个按钮后 --> 转到下一页 --> 重复 --> 发展您的 Linkedin!
这是我的计划,直到我开始遇到问题。 我确实有用于“转到下一页”的功能 --> 我们必须滚动到底部并单击“下一页”。
单击“连接”按钮时,我确实有用于“连接”按钮的功能,所以我可以添加自定义注释并发送连接邀请。
我面临的问题是,当机器人工作时,它会跳过“连接”和“关注”按钮 - 我将附加这部分的代码。
完整代码将是在 github 上 - 完整代码
def process_buttons(driver, base_message, max_requests):
requests_sent = 0
buttons_processed = 0
while buttons_processed < 10:
try:
buttons = driver.find_elements(By.XPATH, "//div[contains(@class, 'entity-result__actions')]/div/button")
if not buttons:
logging.info("No buttons found on this page.")
break
for button in buttons:
if requests_sent >= max_requests:
break
# Check the text content of the button
try:
button_text = button.find_element(By.TAG_NAME, 'span').text.strip()
except NoSuchElementException:
logging.info("No span element found in the button, skipping.")
continue
logging.info(f"Button text: {button_text}")
try:
driver.execute_script("arguments[0].scrollIntoView(true);", button)
time.sleep(1) # Ensure the element is in view
except MoveTargetOutOfBoundsException:
logging.info(f"Move target out of bounds for button with text: {button_text}")
continue
if button_text.lower() == "connect":
try:
logging.info(f"Found Connect button with text: {button_text}")
send_connection_request(driver, button, base_message)
requests_sent += 1
print(requests_sent)
time.sleep(5) # Sleep for 5 seconds after sending each connection request
except Exception as e:
logging.info(f"Skipping already connected or unavailable user: {e}")
continue
elif button_text.lower() == "follow":
try:
logging.info(f"Found Follow button with text: {button_text}")
button.click()
logging.info(f"Followed user with text: {button_text}")
print(requests_sent)
time.sleep(5) # Sleep for 5 seconds after following each user
except Exception as e:
logging.info(f"Error following user: {e}")
continue
elif button_text.lower() == "message":
logging.info(f"Skipping user with Message button: {button_text}")
continue # Skip users with the Message button
buttons_processed += 1
if buttons_processed >= 10:
break
except TimeoutException:
logging.error(f"Timeout while processing buttons.")
break
if not go_to_next_page(driver):
break
def send_connection_requests(driver, search_link, max_requests, base_message):
driver.get(search_link)
while True:
process_buttons(driver, base_message, max_requests)
if not go_to_next_page(driver):
break
我也尝试过仅使用 XPATH。例如,我们知道我们只需要检查 10 个按钮,我尝试获取这 10 个 XPATH 并检查每个按钮是否匹配。不工作。
我可以看出你正在努力让你的 LinkedIn 自动化机器人工作。你在处理按钮时面临的挑战很常见,因为网页加载时间和动态更新的元素会造成干扰。
让我们分析一下问题并探索一些可能解决方案:
为什么你的代码可能会跳过“连接”和“关注”按钮?
-
网页加载时间: 问题很可能在于网页加载速度。你的代码可能会在页面完全加载按钮之前尝试找到并与按钮交互。
time.sleep(1)
可能是无法保证每个按钮都加载完毕。 -
动态加载: LinkedIn 使用无限滚动,这意味着在滚动页面时会加载更多结果。如果你的脚本在所有按钮加载之前执行,它只会看到一部分按钮。
-
Stale Element Reference: 在执行“下一页”操作后,之前找到的按钮引用可能会失效。这意味着你的代码可能指向不再有效的 DOM 中的位置。
可能的解决方案和改进:
-
显式等待:
与
time.sleep()
依赖于固定的等待时间不同,显式等待让你的脚本等待特定的条件满足后再继续执行。在本例中,我们可以使用 Selenium 的WebDriverWait
和expected_conditions
来等待按钮出现在 DOM 中并且可点击:
```python from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC
def process_buttons(driver, base_message, max_requests): # ... your existing code ...
for button in buttons:
# ...
if button_text.lower() == "connect":
try:
# 等待按钮可点击
wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.XPATH, button.get_attribute("xpath"))))
logging.info(f"Found Connect button with text: {button_text}")
send_connection_request(driver, button, base_message)
# ... rest of your code ...
```
- 处理 Stale Element: 如果问题出在 Stale Element 上,你需要在每次迭代中重新定位按钮元素:
```python def process_buttons(driver, base_message, max_requests): requests_sent = 0 buttons_processed = 0
while buttons_processed < 10:
# Find buttons in each iteration
buttons = driver.find_elements(By.XPATH, "//div[contains(@class, 'entity-result__actions')]/div/button")
# ... rest of your code ...
```
- 滚动和加载: 为确保所有动态加载的元素都已加载,请在执行搜索后滚动页面底部:
```python def send_connection_requests(driver, search_link, max_requests, base_message): driver.get(search_link)
while True:
# Scroll to the bottom to load all results
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2) # Give some time for the content to load
process_buttons(driver, base_message, max_requests)
if not go_to_next_page(driver):
break
```
附加提示:
- 错误处理: 实现强大的错误处理机制来优雅地处理意外情况,例如“连接”按钮不可用或出现验证码。
- 限制速度: 自动发送大量请求可能会导致的帐户被 LinkedIn 标记。为了避免这种情况,请在请求之间设置更长的延迟(例如,10-20 秒或更长时间)并限制每天发送的请求总数。
道德方面的考虑:
在实现任何自动化解决方案时,务必考虑道德方面的意义。在 LinkedIn 上大量发送连接请求或消息可能会被视为垃圾邮件,并可能导致的帐户被暂停。请负责任地使用此类自动化,并始终尊重其他用户的体验。
请记住,网站结构可能会发生变化,这可能会导致你的脚本失效。务必定期更新代码以适应这些变化。
希望这些改进和建议能帮助你构建一个更强大可靠的 LinkedIn 自动化机器人!
标签:python,selenium-webdriver,automation,ui-automation From: 78804650