c爬虫抓取网页数据(Python爬虫如何获取JS生成的JS和网页内容和服务端?)
优采云 发布时间: 2022-01-21 01:00c爬虫抓取网页数据(Python爬虫如何获取JS生成的JS和网页内容和服务端?)
最近需要在一个网站中下载一批数据。但是输入一个查询,返回30000到40000个结果,每次只能导出500个,而且每次都要输入下载项的范围!就这样点击下载,我不要命了。所以我想自动化这个过程。
我的需求主要是两点:1.要求自动化程度高。最好有一个成熟的界面,直接模拟浏览器的鼠标和键盘动作,比如输入文本框、选择下拉列表、单选按钮、复选框、点击按钮等。2.效率不高。因为我想要的数据量比较少。3. python下的框架。因为我通常主要使用python。
对网站技术了解不多,对网站只有两个经验:自己开发了一个很简单的Android客户端,用python的scrapy框架写了一个爬虫自动爬取新闻. 所以了解客户端和服务器的一些基本交互方法,了解如何分析网页源代码,了解xpath语法。
当我第一次开始解决这个问题时,我什至不知道要搜索什么。知乎的这个文章提供了很多有用的信息:“Python爬虫如何获取JS生成的URL和网页内容?” 随之权衡了很多方法,最终选择了Selenium。主要优点是学习成本最小,代码实现速度快。缺点是爬取效率低。如果您想成为富有成效的朋友,您将不得不花一些时间学习更复杂的工具包。
网站技术
如果要自动爬取网页,需要了解一些基础知识,这样做会比较快。这里简单介绍一下相关知识。
1. 请求/响应
request 是客户端向服务器发出的请求。输入一个 URL 对应一个请求动作,这是最直观的。爬取静态网页的内容,只需要知道网址即可。但是,当前的许多网页都是动态的。指向或点击网页中的某些元素也会触发请求动作,从而使网页可以动态更新部分内容,而这些内容不能直接从静态网页中获取。这种技术叫做AJAX,但我对它了解不多。这里的问题是我们可能甚至不知道 URL 是什么,所以我们需要一些可以处理动态内容的高级接口。
response 是服务器返回给客户端的内容。如果要获取静态网页内容,直接从请求中获取即可。
2. 分析网页源码
如果我们想抓取网页上的某一部分信息,我们需要知道如何定位它。这里需要 HTML 和 XPATH 知识。不知道的可以去w3school在线教程:
查看网页的源代码,将鼠标指针指向网页的任意位置,或指向目标元素。右键单击并从下拉列表中选择“检查元素”。下面是我右键“百度”显示的网页源代码,是HTML格式的,我们可以看到对应的HTML代码。要提取它,我们可能需要 div//@[class="head_wrapper"]//input[@type="submit"] 的语句,它是 XPATH 语法,易于掌握。知道如何分析网页,我们更进一步。
3. 网页基本元素操作
前进、后退、刷新、打开新标签、输入网址等;
文本框输入、选择下拉列表、单选按钮、复选框、点击按钮等。
我这里只需要模拟这么多操作,可以参考对应的selenium接口。
4. Selenium 简介
底线:Selenium 是用于 Web 应用程序的自动化测试工具集。
很多话:Selenium 诞生于 2004 年,当时 ThoughtWorks 的 Jason Huggins 正在测试一个内部应用程序。作为一个聪明人,他意识到他的时间应该比手动测试每个更改更有价值。他开发了一个驱动页面交互的 Javascript 库,允许多个浏览器自动返回测试结果。该库最终成为 Selenium 的核心,它是 Selenium RC(远程控制)和 Selenium IDE 所有功能的基础。
实战练习1.分析数据采集过程
我的数据采集过程如下:
在A页输入查询语句,点击提交;浏览器自动打开新页面,跳转到新页面B,在文本框中输入下载项的范围;单击导出弹出一个弹出窗口,然后单击下拉列表,单选按钮,选取框进行一些选择,然后单击下载。然后浏览器开始下载文件。
页面 A
B页
2. 爬取过程 A. 安装 Selenium
Selenium 支持多种浏览器,我选择 google chrome。下载链接:。同时,当然要在python中安装selenium。从命令行输入 pip install senenium 进行安装。
B、配置环境变量
这一步需要将chromedriver的保存路径配置到操作系统的环境变量中,这样selenium才能找到chromedriver。windows下配置环境变量PATH,linux或者mac可以选择在.bash_rc中配置。配置方法很多,百度一下。
我用的是mac,不知道为什么配置不行!后来发现只有在代码中设置了才有效。
C. 核心代码(python)
# 设置下载路径,配置ChromeOptions的路径。
chromeoptions = webdriver.ChromeOptions()
首选项 = {'profile.default_content_settings.popups':0,'download.default_directory': query_dir}
chromeoptions.add_experimental_option('prefs', prefs)
# 设置环境变量并启动浏览器。
chromedriver = CHROMEDRIVER_DIR # 设置为你自己的路径
os.environ["webdriver.chrome.driver"] = chromedriver
驱动程序 = webdriver.Chrome(executable_path=chromedriver,chrome_options=chromeoptions)
# 设置不可见等待时间,因为点击网站后,可以返回一段时间的内容。如果不等待,就会报超时异常。
driver.implicitly_wait(IMPLICIT_WAIT_TIME)
# 请求页面A
司机.get("")
# 在页面A的两个文本框中输入并提交。
driver.find_element_by_name('D').clear()
driver.find_element_by_name('D').send_keys('mesz')
driver.find_element_by_name('SEARCH').clear()
driver.find_element_by_name('SEARCH').send_keys(str_search_query)
driver.find_element_by_name('ovid').click()
# 跳转到新窗口并关注该窗口。
current_window_handle = driver.current_window_handle
for hdl in driver.window_handles: # selenium 总是有两个句柄
如果 hdl != current_window_handle:
new_window_handle = hdl
driver.switch_to.window(new_window_handle)
driver.implicitly_wait(IMPLICIT_WAIT_TIME)
# 获取网页。首先获取返回的条目总数,然后提取文本框输入下载条目的范围,例如1-500。然后单击导出。
# 注意:等待页面加载完毕再计算下载次数
search_ret_num = WebDriverWait(驱动程序, EXPLICIT_WAIT_TIME, EXPLICIT_WAIT_INTERVAL).until(EC.presence_of_element_located((By.XPATH,'//*[@id="searchaid-numbers"]')))
search_ret_num =int(re.findall(r'\d+', search_ret_num.text.encode('utf-8'))[0])
list_range = chunks_by_element(范围(1, search_ret_num+1), DOWNLOAD_NUM_PER_TIME)
对于 list_range 中的项目:
download_range = driver.find_element_by_xpath('//*[@id="titles-display"]//input[@title="Range"]')
下载范围.clear()
download_range.send_keys('{}-{}'.format(item[0], item[-1]))
# 点击导出
export = driver.find_element_by_xpath('//*[@id="titles-display"]//input[@value="Export"]')
导出.click()
# 获取弹出窗口。进行一些设置。
driver.switch_to.alert
WebDriverWait(驱动程序, EXPLICIT_WAIT_TIME, EXPLICIT_WAIT_INTERVAL).until(EC.presence_of_element_located((By.XPATH,'//div[@id="export-citation-popup"]')))
# 设置下载文件的一些配置
export_to_options = driver.find_element_by_xpath('//select[@id="export-citation-export-to-options"]')
export_to_options.find_element_by_xpath('//option[@value="xml"]').click()# XML
# 设置引文内容电台
citation_options = driver.find_element_by_xpath('//ul[@id="export-citation-options"]')
citation_options.find_element_by_xpath('//input[@value="ALL"]').click()# 完整参考
# 设置收录复选框
citation_include = driver.find_element_by_xpath('//div[@id="export-citation-include"]')
ifcitation_include.find_element_by_xpath('//input[@name="externalResolverLink"]').is_selected():# 链接到外部解析器
citation_include.find_element_by_xpath('//input[@name="externalResolverLink"]').click()
ifcitation_include.find_element_by_xpath('//input[@name="jumpstartLink"]').is_selected():# 收录网址
citation_include.find_element_by_xpath('//input[@name="jumpstartLink"]').click()
ifcitation_include.find_element_by_xpath('//input[@name="saveStrategy"]').is_selected():# 搜索历史
citation_include.find_element_by_xpath('//input[@name="saveStrategy"]').click()
# 点击下载。
下载 = driver.find_element_by_xpath('//div[@class="export-citation-buttons"]')
下载.click()
最后:
sleep(30)#等待最后一个文件下载完成
# driver.implicitly_wait(30) # 不行!
driver.quit()
返回
3. 提示
A. 每次启动浏览器时,桌面上都会弹出一个浏览器。您可以清楚地看到自动化过程是怎样的。看来 selenium 真的为 Web 程序的自动化测试做好了准备。另外,在爬取过程中要注意保持屏幕打开。如果它进入睡眠或屏幕保护程序,也会抛出异常。
B、在模拟网页操作时,网页跳转是很常见的场景。所以要注意网页响应时间。Selenium 在继续执行代码之前不会等待网页响应完成,而是直接执行。两者应该是不同的过程。这里可以选择设置隐式等待和显式等待。在其他操作中,隐式等待起决定性作用,在WebDriverWait中..显式等待起主要作用,但需要注意的是,最长等待时间取决于两者中的较大者,如果隐式等待时间>显式等待时间,代码的最长等待时间等于隐式等待时间。
C. 设置下载路径时,一开始没有任何效果。怀疑是“download.default_directory”这个key写错了,于是通过查看网页源码找到了key,还是一样。问题出在其他地方。不过提醒了我以后在代码中使用字典进行相关配置的时候,看源码就能猜出来。
D.我以为至少需要两三天才能实现整个过程,因为我真的不明白。从头到尾完成这项研究只需不到一天的时间。大概是因为入手之前找了很久,反复比较之后,才找到了最得心应手的工具。
E. 整理完之后在github上搜了一圈,发现了一个神器。对于想要爬取大量内容的朋友,如果不想浪费时间过多学习web应用的底层知识,可以结合使用Selenium+scrapy。scrapy可以负责搜索网页,selenium负责处理每个网页上的内容,尤其是动态内容。下次如果我需要它,我打算使用这个想法!
F. 分享一句话。“关于爬虫,获取经验最快的方法是:学会写网站,你知道网站发送请求是什么,那么你就知道怎么爬网站了!” 很简单的。,但是这么简单的一句话却给了我很大的启发。之前太难了,一直卡在scrapy爬静态网页的水平。像 cookie 这样的技术也曾被阅读和遗忘过一次。现在看来是因为网站的整体流程还没有理清清楚。另一方面,我也害怕那些复杂的网站技术术语。其实只要在网上查查相关概念,就会慢慢打通。
G. 最后,完全不懂编程的人可以使用一些可视化爬虫工具。这里有一些介绍: 。懂编程又想提高效率的人需要参考其他工具。