c 抓取网页数据(Python爬虫如何获取JS生成的JS和网页内容和服务端?)
优采云 发布时间: 2021-12-10 05:24c 抓取网页数据(Python爬虫如何获取JS生成的JS和网页内容和服务端?)
最近需要在网站下载一批数据。但是当你输入一个查询,返回3万到4万条结果时,一次只能导出500条,而且每次都要输入下载项的范围!这样点击下载,又不是我的命。所以我想自动化这个过程。
我的需求主要有两点:1.需要高度自动化。最好有一个成熟的界面,直接模拟浏览器的鼠标和键盘的动作,比如在文本框中输入、选择下拉列表、单选按钮、复选框、点击按钮等。2. 不需要效率。因为我要的数据量比较少。3. python下的框架。因为平时用的最多的是python。
我对网站的技术了解不多,对网站的经验只有两个:我开发了一个非常简单的Android客户端,并使用python scrapy框架写了一个爬虫来自动抓取新闻。所以了解客户端和服务端的一些基本交互方法,了解如何分析网页源代码,了解xpath语法。
一开始针对这个问题,我什至不知道要搜索什么。知乎的文章文章提供了很多有用的信息:《Python爬虫如何获取JS生成的URL和网页内容?》一路上权衡了很多方法,最后选择了Selenium。主要优点是学习成本非常小,代码实现速度快。缺点是爬行效率低。对于那些想要提高效率的人来说,他们必须花一些时间学习更复杂的工具包。
网站技术
如果你想自动抓取网页,你必须了解一些基本知识,这样做会更快。下面简单介绍一下相关知识。
1. 请求/响应
请求是客户端向服务器发起请求。输入一个 URL 对应一个请求动作,这是最直观的。要抓取静态网页的内容,您只需要知道 URL。然而,今天的许多网页都是动态的。指向或点击网页的某些元素也会触发请求动作,这会导致网页动态更新部分内容。这部分内容无法直接从静态网页中获取。这种技术叫做AJAX,但我不太明白。这里的问题是我们可能不知道 URL 是什么,因此需要一些高级接口来处理动态内容。
响应是服务器返回给客户端的内容。如果要获取静态网页的内容,直接从请求中获取即可。
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,在文本框中输入下载项的范围;点击Export,弹出一个弹窗,然后点击下拉列表,单选按钮,勾选Check the box做一些选择,点击下载。然后浏览器开始下载文件。
A页
页面 B
2. 爬取过程 A. 安装 Selenium
Selenium 支持多种浏览器,我选择谷歌浏览器。下载链接:。同时,当然python中必须安装selenium。从命令行输入 pip install senenium 进行安装。
B. 配置环境变量
这一步需要配置chromedriver的保存路径到操作系统的环境变量中,这样selenium才能找到chromedriver。windows下配置环境变量PATH,linux或mac可以选择在.bash_rc中配置。配置方法很多,自行百度。
我用的是mac,但不知道为什么配置不起作用!后来我发现只有在代码中设置才能工作。
C. 核心代码(python)
# 设置下载路径并配置ChromeOptions的路径。
chromeoptions = webdriver.ChromeOptions()
prefs = {'profile.default_content_settings.popups':0,'download.default_directory': query_dir}
chromeptions.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
driver.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(driver, 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(range(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"]')
出口。点击()
# 获取弹出窗口。进行一些设置。
driver.switch_to.alert
WebDriverWait(driver, 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():# 收录 URL
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()
# 点击下载。
download = driver.find_element_by_xpath('//div[@class ="export-citation-buttons"]')
下载。点击()
最后:
sleep(30)#等待最后一个文件下载完成
# driver.implicitly_wait(30) # 不起作用!
驱动程序退出()
返回
3. 提示
A. 每次启动浏览器,桌面上都会弹出一个浏览器。您可以清楚地看到自动化过程是如何进行的。看来selenium真的是为web程序的自动化测试做好了准备。此外,在抓取过程中保持屏幕打开。如果您进入睡眠或屏幕保护程序,也会抛出异常。
B、在模拟网页操作时,网页跳转是一个很常见的场景。所以要注意网页响应时间。Selenium 不会等待网页响应完成才继续执行代码,它会直接执行。两者应该是不同的过程。这里可以选择设置隐式等待和显式等待。在其他操作中,隐式等待起决定作用,显式等待在WebDriverWait中起主要作用。 但是需要注意的是,最长等待时间取决于两者中较大的一个,如果隐式等待时间>显式等待时间,代码的最长等待时间等于隐式等待时间。
C、设置下载路径时,一开始不起作用。我怀疑是“download.default_directory”这个键错了,于是查看网页源码找到了这个键,还是一样。问题出在别处。但这提醒我,以后在代码中使用字典做相关配置的时候,看源码就可以猜到了。
D.我以为整个过程要两三天才能实现,因为我真的不明白。从开始学习到完成,不到一天就完成了。可能是因为我在开始之前搜索了很长时间,经过反复比较,找到了最方便的工具。
E. 做完之后在github上搜了一下,发现了一个神器。对于想要爬取大量内容的朋友,如果不想浪费时间学习太多web应用的底层知识,可以结合使用Selenium+scrapy。Scrapy 可以负责搜索网页,而 selenium 负责处理每个网页上的内容,尤其是动态内容。如果下次有需要,我打算用这个主意!
F. 分享一句话。“关于爬虫,最快获得经验的方法是:学会写网站,如果你知道网站在请求什么,你就会知道怎么爬网站!” 这很简单。,但是这么简单的一句话给了我很大的启发。之前感觉太难了,一直卡在scrapy爬静态网页的级别。像cookies这样的技术也曾被观看过一次,一次被遗忘一次。现在看来是因为网站的整体流程没有梳理清楚。另一方面,我也害怕那些复杂的网站技术术语。其实只要去网上查一下相关概念是怎么回事,就慢慢熬过去了。
G. 最后,完全不懂编程的人可以使用一些可视化爬虫工具。下面是一些介绍:。懂编程又想高效率的需要参考其他工具。