使用BS4和Selenium实现高级网页数据采集的实战指南(爬取知乎数据)

2023年 10月 13日 98.5k 0

前言:

最近因为一些原因,需要收集一些知乎的数据进行分析。但当实际操作时却发现遇到了种种问题.首当其冲的就是知乎的反爬机制.最初我的思路是先手动登录,然后提取并存放cookie信息到本地以方便以后使用.然后重新打开后再读取cookie然后刷新页面,结果遇到了和这篇博文一样的情况.重磅!!!惊现知乎新反爬_知乎反爬-CSDN博客

image.png
虽然能成功登录和访问问答,但当我获取搜索结果和点击展开评论时会报错.
经过一段时间的查阅和尝试后写下了这篇博客.

最初的思路:

不完整代码如下:

driver.get('https://www.zhihu.com')
# 暂停程序执行,等待一段时间(60秒),以确保网页加载完全
time.sleep(30)
# 获取当前页面的所有 cookie 信息,并将其存储为字典
dictCookies = driver.get_cookies()
# 将字典形式的 cookies 转换成 JSON 格式的字符串
jsonCookies = json.dumps(dictCookies)
print(jsonCookies)

# 将 JSON 格式的 cookies 写入到名为 "cookies_juejin.json" 的文件中
with open("cookies_zhihu.json", "w") as fp:
    fp.write(jsonCookies)
# 关闭浏览器
driver.quit()

# 创建一个 Firefox 浏览器的实例
browser = webdriver.Firefox(options=options)


# 打开指定网页
browser.get("https://www.zhihu.com")
# 删除当前浏览器中的所有 cookie 信息
# browser.delete_all_cookies()
# 从名为 "cookies_juejin.json" 的文件中读取之前保存的 JSON 格式的 cookies
# with open('cookies_zhihu.json', 'r', encoding='utf-8') as f:
#     listCookies = json.loads(f.read())
# # 将读取到的 cookies 添加到当前浏览器中
# for cookie in listCookies:
#     browser.add_cookie(cookie)
# 再次访问网页,这次将包含之前保存的 cookie 信息,实现自动登录
browser.refresh()

使用Selenium来登录知乎,然后将获取到的cookies保存到一个JSON文件中,以便后续使用。在浏览器刷新时加载这些cookies,以实现自动登录。然而会遇到之前所说的那种问题,开始思考是哪里被发现了.

被发现的原因

经过查阅后发现,
Selenium容易被检测的主要原因在于它所创建的浏览器指纹与手动操作所创建的浏览器指纹不同。一个常见的检测方法是通过检查window.navigator.webdriver这个关键字。在使用Selenium打开的浏览器中,该关键字的打印结果通常为true,而在正常手动操作的浏览器中,打印结果则为undefined。网站可以通过比较这些关键字的返回值来检测是否有自动化操作的迹象。这就是为什么Selenium容易被检测到的原因之一。

如何绕过

修改window.navigator.webdriver关键字返回结果.

options = webdriver.ChromeOptions()
# 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
driver = webdriver.Chrome(options=options)
# js注入,修改webdriver返还
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})


driver.get('https://www.zhihu.com')

这段代码的关键点在于使用Chrome浏览器的开发者模式,同时通过CDP注入js,将navigator.webdriver的返回值修改为undefined。这样,网站在检测navigator.webdriver时会返回undefined,不再能够轻易检测到Selenium的使用。

然而,因为浏览器指纹很多,这种方法的局限性是显而易见的。不过配合手动登录,已经能获取服务器信任了.而是用cookie登录的话还是会出现之前的情况.

自动化操作

def finddata():
    input = driver.find_element(By.ID,'Popover1-toggle')
    input.send_keys('南阳市旅游景点')
    time.sleep(3)
    element =driver.find_element(By.CLASS_NAME, 'Popover')
    button= wait.until(EC.visibility_of_element_located((By.TAG_NAME, 'button')))
    # element.click()
    #  = element.find_element(By., 'button')

    button.click()
    time.sleep(5)

首先查找了一个具有特定ID的输入框,然后在输入框中输入了文本。接着,它等待页面加载,查找了一个具有特定CLASS_NAME的元素,然后使用ExpectedConditions等待,确保一个按钮元素可见,并点击该按钮。

image.png

image.png

bs4提取数据

def gethtml():
    # 获取网页源代码
    page_source = driver.page_source
    # 使用 BeautifulSoup 解析源代码
    soup = BeautifulSoup(page_source, 'html.parser')
    # print(soup)
    # print(soup.select('.entry-list .item .entry .content-wrapper .content-main .title-row'))
    for child in  soup.select('.ListShortcut .css-0 .ContentItem-title'):
        print(child.find('div').find('a')['href'],child.find('div').find('span').text)

首先使用driver.page_source获取网页的HTML源代码,然后使用BeautifulSoup库来解析HTML。它遍历了具有特定CSS选择器的元素。在循环中,代码使用.find()方法来查找特定元素,然后提取链接和文本信息,并将它们打印出来。

image.png

成果展示:

爬取到的url和标题.
image.png

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论