jquery抓取网页内容

jquery抓取网页内容

新手学爬虫的人多了去了我这本书

网站优化优采云 发表了文章 • 0 个评论 • 69 次浏览 • 2022-05-13 11:01 • 来自相关话题

  新手学爬虫的人多了去了我这本书
  jquery抓取网页内容(最好https),推荐看下这个,分享下我自己总结的一些爬虫基础知识。想学习爬虫的朋友,
  我是从《老子》这本书入门的,看了三天,几乎到了语文老师教学时都会做的题目和写的作文,然后然后就开始啃python爬虫了。发现挺多很基础的东西,挺适合新手学的,知识清晰,各种代码规范,js的劫持方法,的体验做的很好,这本书看了两遍,
  python三大范式那块去掉。python特色就是解释型。初学python的话,官方有大量教程,特别是第二版,可以当python基础教程。当你写了一大堆的爬虫程序后,你会明白自己到底不太明白python的特性。爬虫这个东西吧,就跟写小说,差不多。小说需要很多工具(用户设置、故事情节)。爬虫也一样,一般都是把已有的东西动态地找过来加以改造。
  不然你能不能写好东西完全取决于你的技术和你的生活环境。python的范式就是清晰不含糊。python从03版开始就有很多标准库,这几年python发展的非常好,包很多,这就是标准库的好处。基础很好的人去学这个语言很有优势。以上都是废话。想学爬虫的人多了去了,你来我这看看有没有人回答吧。祝好运。 查看全部

  新手学爬虫的人多了去了我这本书
  jquery抓取网页内容(最好https),推荐看下这个,分享下我自己总结的一些爬虫基础知识。想学习爬虫的朋友,
  我是从《老子》这本书入门的,看了三天,几乎到了语文老师教学时都会做的题目和写的作文,然后然后就开始啃python爬虫了。发现挺多很基础的东西,挺适合新手学的,知识清晰,各种代码规范,js的劫持方法,的体验做的很好,这本书看了两遍,
  python三大范式那块去掉。python特色就是解释型。初学python的话,官方有大量教程,特别是第二版,可以当python基础教程。当你写了一大堆的爬虫程序后,你会明白自己到底不太明白python的特性。爬虫这个东西吧,就跟写小说,差不多。小说需要很多工具(用户设置、故事情节)。爬虫也一样,一般都是把已有的东西动态地找过来加以改造。
  不然你能不能写好东西完全取决于你的技术和你的生活环境。python的范式就是清晰不含糊。python从03版开始就有很多标准库,这几年python发展的非常好,包很多,这就是标准库的好处。基础很好的人去学这个语言很有优势。以上都是废话。想学爬虫的人多了去了,你来我这看看有没有人回答吧。祝好运。

网络爬虫与网页自动化操作:最小化版系统学习的大纲

网站优化优采云 发表了文章 • 0 个评论 • 280 次浏览 • 2022-05-12 02:08 • 来自相关话题

  网络爬虫与网页自动化操作:最小化版系统学习的大纲
  
  我是DJun(小丁),码龄18年,从事IT工作5年,踩过无数“语言”坑最后入坑Python,想通过公众号,把自己的成长经历与经验分享给朋友们。
  同名酷安看看号“好想学Python”已开通,欢迎订阅。
  本篇摘要
  “网络爬虫”“网页自动化”听起来很神秘,其实入门并不会特别难。目前网络上关于Python爬虫的资料层出不穷。博文大多以具体应用内容为目标用简短代码实现基本功能,但缺乏大纲展现;网络视频教程或者书籍的覆盖较为全面,但缺乏灵活使用的经验总结。本篇介绍入门它们至少需要了解和学习的知识点,希望对需要的朋友有所帮助。
  往期精选
  >>>
  >>>
  >>>
  >>>
  >>>
  >>>
  >>>
  01
  什么是“网络爬虫”?什么是“网页自动化”?
  “网络爬虫”是一种在网络上获取公开数据的操作方式,是一种获取网络上数据的程序或者脚本。常见的,比如某电影网站的电影评分数据、评论信息分析,比如某商品在各大电商平台的价位走势对比,等等,这些数据分析所用数据来源大多是通过爬虫获取的。
  “网页自动化”是一种自动去操作网页浏览器实现某些测试目的的操作方式,是一种自动操作浏览器的程序或者脚本。常见的,比如Web开发者测试网站,比如抢车票、抢优惠券,等等。
  02
  为什么选用Python做它们的开发?
  爬虫的本质是进行HTTP请求、获取数据、解析数据,网页自动化的本质是对浏览器程序发送操作指令,而Python等程序语言只是一种工具,大多数语言都可以实现前面所述的操作。Python因其语言特性灵活、易用性高、扩展性强、跨平台,快速开发,从各方面来看都极适合做“网络爬虫”“网页自动化”的开发。
  03
  系统学习的最小化版大纲内容
  整体学习思路:数据存储结构——网页基础知识——程序开发应用
  
  01
  数据存储结构
  ① JSON/BSON
  JSON是JavaScript Object Notation的缩写,意为JS对象简谱,是一种轻量级的数据交换格式。由于其易于人阅读和编写,同时也易于机器解析和生成,并能有效地提升网络传输效率,不论是在解析爬虫数据上,还是在程序中保存本地数据上,都非常好用。
  BSON 缩写看起来很像JSON,它是Binary Serialized Document Format的缩写,意为二进制序列化式文档格式,是一种二进制存储格式,也可以做为网络数据交换的一种存储形式,具有轻量性、可遍历性、高效性的特点,常见于时常用于爬虫数据记录的MongoDB这种文档型数据库中,使用起来跟JSON并无太大差异。在MongoDB 数据库上可以以类似JSON的形式将文档数据写入数据库。
  在Python中,操作JSON的模块叫json,是自带模块;操作MongoDB的第三方模块叫pymongo,可以通过pip命令直接安装。
  ②CSV
  CSV是Comma-Separated Values的缩写,意为字符分隔值,是最常见的纯文本形式保存数据的格式。简单形容它的格式内容,通常是每行包含一个数据记录,同一行中用逗号对每列数据进行分隔,单行数据是像“1,Tom,male,18,student”这样的形式。
  大多数人对这种格式的数据有一些误解,一个是它能用Excel打开,所以误称之为“Excel表文件”;一个是它每列数据都用逗号间隔,但不了解它的引号有“转义”的作用,可以对逗号、引号本身作转义。
  通过改变“逗号”列分隔符、“引号”转义符、“回车”行分隔符的符号约定,可以产生各种变体,但实质都遵守类似CSV格式的规则。
  在Python中,操作CSV的模块叫csv,是自带模块。
  ③TEXT
  TEXT通常指纯文本数据,是最常见的文本数据格式,一般通过纯文本编辑器(比如记事本)直接打开即可阅读内容。
  但需要留意的是,文本数据通常有“字符编码”的问题,因为底层是用字节数据储存的,显示成什么样的文字是“字符编码”决定的,但具体到某个文件的字符编码是“GBK”还是“UTF-8”又是文件内容决定的;也需要留意的是,CSV的本质是纯文本文件,也会有同样的“字符编码”的问题,用Excel直接打开CSV文件是最糟糕的选择,通常在Windows中文系统下Excel打开CSV文件默认只解析GBK编码。推荐使用EmEditor、Notepad++打开这类文件。
  在Python中,操作TEXT通常通过直接的文件打开进行操作(open(),mode为'r'或'w')。
  ④XML
  XML是Extensible Markup Language的缩写,意为可扩展标记语言,是一种通用的用于标记电子文件使其具有结构性的标记语言。它也可以存储数据,可以作标签、标记属性,还可以展现层级关系。用于展示网页内容的HTML超文本标记语言可以看成是它的子集。
  在Python中,操作XML通常用第三方模块lxml进行操作,简单易用,可以通过pip命令直接安装。
  ⑤数据库
  数据库是按照数据结构来组织、存储和管理数据的仓库。分为关系型数据库(SQLite、MySQL、Oracle、PostgreSQL等),非关系型数据库(Redis、MongoDB、Neo4J等)。关系型数据库通过SQL语句操作数据,效率非常高;非关系型数据库由于优化了查找性能和存储结构,常用于内容缓存、分布式文件系统、Web应用等。
  SQLite是一款轻型关系型数据库,支持存储在单一文件中或内存中,而且Python自带SQLite的操作模块叫sqlite3,如果应用场景的要求并不高,用它很合适。
  关系型数据库推荐学习MySQL,目前属于Oracle旗下产品,开源、体积小、速度快,一般中小型网站的开发都会选择它作为网站数据库。
  非关系型数据库推荐学习MongoDB,由于采用BSON进行文档存储,在网络爬虫应用中非常好用。
  02
  网页基础知识
  ①HTML
  HTML是HyperText Markup Language的缩写,意为超文本标记语言。对HTML最直观的的感受是在我们浏览网页的时候,在页面上所见到的内容。
  爬虫的其中一种操作方式是,获取到HTML的源码数据,然后对其解析得到我们需要的数据内容。
  浏览器可以直接查看HTML源码,通过自带的“开发者工具”(一般是按F12呼出),既可以分析代码,也可以在其中的Console里执行调试JS代码。在这里分析得到数据所在路径后,就可以很轻松地编写代码进行爬取了。
  ②JavaScript
  JS,即JavaScript,是一种直译式脚本语言,可以用于给HTML网页增加动态功能。JavaScript引擎现已经成为浏览器的一部分。
  在爬虫应用中,JS通常用于改变网页内容(比如去水印),或者获取以JS之外的方式难获取的网页内容,等;在网页自动化应用中,JS通常用于高级操作(比如下拉刷新),或者直接调用JS函数得到所需数据,等。
  ③XPath/CSS Selector
  XPath是XML路径的意思,它是一种用来确定XML文档中某部分位置的强大语言。
  CSS Selector是CSS选择器的意思,它是一种与XPath不同语法,但作用相似、功能同样强大的语言,一般用于CSS上。
  通过XPath、CSSSelector这两件利器,总结具体网页的HTML元素排列规律,可以精准定位到我们所需要的数据的相关元素上,在某种程度上比以面向对象方式定位网页元素的操作(通常以BeautifulSoup作为代表)更为便捷。
  第三方模块lxml支持XPath定位元素的操作;第三方模块PyQuery模仿jQuery方式处理HTML,可以使用与jQuery同款的CSSSelector定位元素;第三方模块selenium同时支持XPath和CSS Selector定位元素的操作。
  03
  程序开发应用
  ①Python模块:lxml +json + re +requests +selenium
  在爬虫应用中,requests、selenium担当获取数据的角色,lxml、json、re担当解析数据的角色。requests适用于不需要JavaScript渲染就可以获取得到的网页数据或者API返回结果数据(比如百度搜索结果,天气JSON API)的情景,selenium适用于需要JavaScript渲染的情景(比如微博,空间,下拉刷新)。从requests或selenium获取到content或者page_source之后,根据数据类型进行处理,如果是json类型就用json模块解析,如果是HTML源码则用lxml解析。
  在网页自动化应用中,selenium担当向浏览器发送控制指令的控制者角色,只要把需要做的自动操作通过程序代码直接实现即可。
  笔者并不是很推荐用第三方模块BeautifulSoup进行HTML解析,在大多数情况下,它没有XPath那么简洁有力。
  正则表达式解析(Python自带的re模块)在某些情况下甚是好用,但笔者建议,目前大多数解析数据的方式都可以通过HTML解析得到,较少出现需要正则表达式解析的情况,正则表达式的编写和维护相对XPath等较难,可以不用正则的时候尽量不要使用。
  可能听说过像Scrapy这样的强大的爬虫框架,笔者建议初入门的朋友先跳过Scrapy,先掌握上述几个最常用的模块,之后再接触它。
  ②抓包工具:Fiddler
  Fiddler官方地址:
  通过Fiddler可以很方便地在访问网站的过程中进行抓包操作,其中一种应用情景是,找出在网页显示我们所要抓取的内容的背后可能进行的后台数据请求操作,然后配合requests模块直接把需要的数据一举抓取下来。
  ③面向对象:类(class)
  网络博文在讲解具体爬虫应用时,往往为了简略实现,不会以面向对象的思维来写爬虫。优秀的项目代码例子较为少见。
  在先前笔者的文章《面向你的对象,写一手漂亮的类》()中提到,面向对象可以“帮助我们更好地组织程序代码,在提高效率的同时,在程序内部实现高内聚、低耦合,后期维护也很方便”。而“网络爬虫”“网页自动化”的应用要形成一个大的项目规模的时候,必须在一开始的时候就以面向对象的思维进行思考,构建整个项目的框架,再逐步开发。
  一个完整的“网络爬虫”项目,通常会包括获取数据、解析数据、保存数据等这几部分;而一个完整的“网页自动化”项目,通常会包括实施者的配置、实施操作步骤、记录操作结果等这几部分。编写代码时,可以分别对每个部分进行包装,并且把具体数据(比如网址URL、抓取规则、操作步骤数据)从代码中分离出来,从外部读入,程序代码内只实现固定不变的那几部分。
  在做爬虫程序练习时,通常是以一个具体的实现目标来做的,我们可以就着这样的练习机会,把它们分别都当做是一个个的小项目对待,多参考相关资料,用面向对象的思维边学边做,从一个小的项目里把类包装完整,再拷贝到新的小项目中把它们复用起来。这样不仅能提升代码能力,而且积累出来的代码复用性会随着每一次的迁移、改进不断地提高,可以很大程度节省学习时间和开发新程序的成本。
  
  希望本篇可以给感兴趣或者想要学习的朋友们带来帮助哈。
  有其他疑问也请在下方留言提出,会尽力解答~ 查看全部

  网络爬虫与网页自动化操作:最小化版系统学习的大纲
  
  我是DJun(小丁),码龄18年,从事IT工作5年,踩过无数“语言”坑最后入坑Python,想通过公众号,把自己的成长经历与经验分享给朋友们。
  同名酷安看看号“好想学Python”已开通,欢迎订阅。
  本篇摘要
  “网络爬虫”“网页自动化”听起来很神秘,其实入门并不会特别难。目前网络上关于Python爬虫的资料层出不穷。博文大多以具体应用内容为目标用简短代码实现基本功能,但缺乏大纲展现;网络视频教程或者书籍的覆盖较为全面,但缺乏灵活使用的经验总结。本篇介绍入门它们至少需要了解和学习的知识点,希望对需要的朋友有所帮助。
  往期精选
  >>>
  >>>
  >>>
  >>>
  >>>
  >>>
  >>>
  01
  什么是“网络爬虫”?什么是“网页自动化”?
  “网络爬虫”是一种在网络上获取公开数据的操作方式,是一种获取网络上数据的程序或者脚本。常见的,比如某电影网站的电影评分数据、评论信息分析,比如某商品在各大电商平台的价位走势对比,等等,这些数据分析所用数据来源大多是通过爬虫获取的。
  “网页自动化”是一种自动去操作网页浏览器实现某些测试目的的操作方式,是一种自动操作浏览器的程序或者脚本。常见的,比如Web开发者测试网站,比如抢车票、抢优惠券,等等。
  02
  为什么选用Python做它们的开发?
  爬虫的本质是进行HTTP请求、获取数据、解析数据,网页自动化的本质是对浏览器程序发送操作指令,而Python等程序语言只是一种工具,大多数语言都可以实现前面所述的操作。Python因其语言特性灵活、易用性高、扩展性强、跨平台,快速开发,从各方面来看都极适合做“网络爬虫”“网页自动化”的开发。
  03
  系统学习的最小化版大纲内容
  整体学习思路:数据存储结构——网页基础知识——程序开发应用
  
  01
  数据存储结构
  ① JSON/BSON
  JSON是JavaScript Object Notation的缩写,意为JS对象简谱,是一种轻量级的数据交换格式。由于其易于人阅读和编写,同时也易于机器解析和生成,并能有效地提升网络传输效率,不论是在解析爬虫数据上,还是在程序中保存本地数据上,都非常好用。
  BSON 缩写看起来很像JSON,它是Binary Serialized Document Format的缩写,意为二进制序列化式文档格式,是一种二进制存储格式,也可以做为网络数据交换的一种存储形式,具有轻量性、可遍历性、高效性的特点,常见于时常用于爬虫数据记录的MongoDB这种文档型数据库中,使用起来跟JSON并无太大差异。在MongoDB 数据库上可以以类似JSON的形式将文档数据写入数据库。
  在Python中,操作JSON的模块叫json,是自带模块;操作MongoDB的第三方模块叫pymongo,可以通过pip命令直接安装。
  ②CSV
  CSV是Comma-Separated Values的缩写,意为字符分隔值,是最常见的纯文本形式保存数据的格式。简单形容它的格式内容,通常是每行包含一个数据记录,同一行中用逗号对每列数据进行分隔,单行数据是像“1,Tom,male,18,student”这样的形式。
  大多数人对这种格式的数据有一些误解,一个是它能用Excel打开,所以误称之为“Excel表文件”;一个是它每列数据都用逗号间隔,但不了解它的引号有“转义”的作用,可以对逗号、引号本身作转义。
  通过改变“逗号”列分隔符、“引号”转义符、“回车”行分隔符的符号约定,可以产生各种变体,但实质都遵守类似CSV格式的规则。
  在Python中,操作CSV的模块叫csv,是自带模块。
  ③TEXT
  TEXT通常指纯文本数据,是最常见的文本数据格式,一般通过纯文本编辑器(比如记事本)直接打开即可阅读内容。
  但需要留意的是,文本数据通常有“字符编码”的问题,因为底层是用字节数据储存的,显示成什么样的文字是“字符编码”决定的,但具体到某个文件的字符编码是“GBK”还是“UTF-8”又是文件内容决定的;也需要留意的是,CSV的本质是纯文本文件,也会有同样的“字符编码”的问题,用Excel直接打开CSV文件是最糟糕的选择,通常在Windows中文系统下Excel打开CSV文件默认只解析GBK编码。推荐使用EmEditor、Notepad++打开这类文件。
  在Python中,操作TEXT通常通过直接的文件打开进行操作(open(),mode为'r'或'w')。
  ④XML
  XML是Extensible Markup Language的缩写,意为可扩展标记语言,是一种通用的用于标记电子文件使其具有结构性的标记语言。它也可以存储数据,可以作标签、标记属性,还可以展现层级关系。用于展示网页内容的HTML超文本标记语言可以看成是它的子集。
  在Python中,操作XML通常用第三方模块lxml进行操作,简单易用,可以通过pip命令直接安装。
  ⑤数据库
  数据库是按照数据结构来组织、存储和管理数据的仓库。分为关系型数据库(SQLite、MySQL、Oracle、PostgreSQL等),非关系型数据库(Redis、MongoDB、Neo4J等)。关系型数据库通过SQL语句操作数据,效率非常高;非关系型数据库由于优化了查找性能和存储结构,常用于内容缓存、分布式文件系统、Web应用等。
  SQLite是一款轻型关系型数据库,支持存储在单一文件中或内存中,而且Python自带SQLite的操作模块叫sqlite3,如果应用场景的要求并不高,用它很合适。
  关系型数据库推荐学习MySQL,目前属于Oracle旗下产品,开源、体积小、速度快,一般中小型网站的开发都会选择它作为网站数据库。
  非关系型数据库推荐学习MongoDB,由于采用BSON进行文档存储,在网络爬虫应用中非常好用。
  02
  网页基础知识
  ①HTML
  HTML是HyperText Markup Language的缩写,意为超文本标记语言。对HTML最直观的的感受是在我们浏览网页的时候,在页面上所见到的内容。
  爬虫的其中一种操作方式是,获取到HTML的源码数据,然后对其解析得到我们需要的数据内容。
  浏览器可以直接查看HTML源码,通过自带的“开发者工具”(一般是按F12呼出),既可以分析代码,也可以在其中的Console里执行调试JS代码。在这里分析得到数据所在路径后,就可以很轻松地编写代码进行爬取了。
  ②JavaScript
  JS,即JavaScript,是一种直译式脚本语言,可以用于给HTML网页增加动态功能。JavaScript引擎现已经成为浏览器的一部分。
  在爬虫应用中,JS通常用于改变网页内容(比如去水印),或者获取以JS之外的方式难获取的网页内容,等;在网页自动化应用中,JS通常用于高级操作(比如下拉刷新),或者直接调用JS函数得到所需数据,等。
  ③XPath/CSS Selector
  XPath是XML路径的意思,它是一种用来确定XML文档中某部分位置的强大语言。
  CSS Selector是CSS选择器的意思,它是一种与XPath不同语法,但作用相似、功能同样强大的语言,一般用于CSS上。
  通过XPath、CSSSelector这两件利器,总结具体网页的HTML元素排列规律,可以精准定位到我们所需要的数据的相关元素上,在某种程度上比以面向对象方式定位网页元素的操作(通常以BeautifulSoup作为代表)更为便捷。
  第三方模块lxml支持XPath定位元素的操作;第三方模块PyQuery模仿jQuery方式处理HTML,可以使用与jQuery同款的CSSSelector定位元素;第三方模块selenium同时支持XPath和CSS Selector定位元素的操作。
  03
  程序开发应用
  ①Python模块:lxml +json + re +requests +selenium
  在爬虫应用中,requests、selenium担当获取数据的角色,lxml、json、re担当解析数据的角色。requests适用于不需要JavaScript渲染就可以获取得到的网页数据或者API返回结果数据(比如百度搜索结果,天气JSON API)的情景,selenium适用于需要JavaScript渲染的情景(比如微博,空间,下拉刷新)。从requests或selenium获取到content或者page_source之后,根据数据类型进行处理,如果是json类型就用json模块解析,如果是HTML源码则用lxml解析。
  在网页自动化应用中,selenium担当向浏览器发送控制指令的控制者角色,只要把需要做的自动操作通过程序代码直接实现即可。
  笔者并不是很推荐用第三方模块BeautifulSoup进行HTML解析,在大多数情况下,它没有XPath那么简洁有力。
  正则表达式解析(Python自带的re模块)在某些情况下甚是好用,但笔者建议,目前大多数解析数据的方式都可以通过HTML解析得到,较少出现需要正则表达式解析的情况,正则表达式的编写和维护相对XPath等较难,可以不用正则的时候尽量不要使用。
  可能听说过像Scrapy这样的强大的爬虫框架,笔者建议初入门的朋友先跳过Scrapy,先掌握上述几个最常用的模块,之后再接触它。
  ②抓包工具:Fiddler
  Fiddler官方地址:
  通过Fiddler可以很方便地在访问网站的过程中进行抓包操作,其中一种应用情景是,找出在网页显示我们所要抓取的内容的背后可能进行的后台数据请求操作,然后配合requests模块直接把需要的数据一举抓取下来。
  ③面向对象:类(class)
  网络博文在讲解具体爬虫应用时,往往为了简略实现,不会以面向对象的思维来写爬虫。优秀的项目代码例子较为少见。
  在先前笔者的文章《面向你的对象,写一手漂亮的类》()中提到,面向对象可以“帮助我们更好地组织程序代码,在提高效率的同时,在程序内部实现高内聚、低耦合,后期维护也很方便”。而“网络爬虫”“网页自动化”的应用要形成一个大的项目规模的时候,必须在一开始的时候就以面向对象的思维进行思考,构建整个项目的框架,再逐步开发。
  一个完整的“网络爬虫”项目,通常会包括获取数据、解析数据、保存数据等这几部分;而一个完整的“网页自动化”项目,通常会包括实施者的配置、实施操作步骤、记录操作结果等这几部分。编写代码时,可以分别对每个部分进行包装,并且把具体数据(比如网址URL、抓取规则、操作步骤数据)从代码中分离出来,从外部读入,程序代码内只实现固定不变的那几部分。
  在做爬虫程序练习时,通常是以一个具体的实现目标来做的,我们可以就着这样的练习机会,把它们分别都当做是一个个的小项目对待,多参考相关资料,用面向对象的思维边学边做,从一个小的项目里把类包装完整,再拷贝到新的小项目中把它们复用起来。这样不仅能提升代码能力,而且积累出来的代码复用性会随着每一次的迁移、改进不断地提高,可以很大程度节省学习时间和开发新程序的成本。
  
  希望本篇可以给感兴趣或者想要学习的朋友们带来帮助哈。
  有其他疑问也请在下方留言提出,会尽力解答~

【编程课堂】以 jQuery 之名 - 爬虫利器 PyQuery

网站优化优采云 发表了文章 • 0 个评论 • 76 次浏览 • 2022-05-09 13:36 • 来自相关话题

  【编程课堂】以 jQuery 之名 - 爬虫利器 PyQuery
  
  根据 id 定位找到这个li标签,代码如下:
  # 定位 id = note-11772642 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />pq_id = pq('#note-11772642')
  以上代码获取id名为note-11772642的标签,需要注意的是查询 id 时添加#前缀,这是 css 选择器语法。
  根据 class 定位:
  同样以刚才的为例
  
  我们根据class=have-img去获取这个li标签
  # 定位 class = have-img 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />pq_class = pq('.have-img')
  注意的是查询class时添加.前缀,这也是 css 选择器语法。
  2.3 索引标签
  在上一节的最后有个小问题,我们知道head标签在 html 中只有一个,而class名为have-img的li标签可能有多个,我们该
  如何遍历所有的li标签呢? 又该如何单独的取某一个li呢?
  首先我们可以逐个遍历
  # 遍历所有 class = have-img 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />for li in pq_class:    <br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />    # 获取每一个 li 标签
   pq_li = pq(li)
  我们可以索引某一个li标签
  使用.ep(index)函数。
  # 获取第一个 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_first = pq_class.ep(0)<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" /># 获取第二个 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_second = pq_class.ep(1)
  2.4 寻找标签
  同样回到刚刚的那张图
  
  在上一步,我们已经找到了所有的li标签,也知道如何取索引其中的元素,但我们现在要准确定位到某一个元素,比如上图中id = note-11772642这个li标签。
  这时候filter(selecter)就派上了用场
  li_spec = pq_class.filter('#note-11772642')
  这样我们就找到了指定的这个li标签,需要注意的是,filter函数只能在同一级标签中寻找,比如在这里只能过滤li标签,而不能定位li标签下的a标签、div标签等。
  当然,针对这种情况, pyquery 为我们提供了另外一个函数find(selector),该函数用于寻找子节点,继续以上图为例,寻找该特定 li 标签下的 p 标签
  p_tag = li_spec.find('p')
  2.5 提取属性与值
  以上我们讲了许多关于标签的知识,现在来谈谈怎么获取标签内的属性和标签包裹的文本,实际的爬虫项目中,通常这是最重要的一步,比如从a标签中获取链接、从li标签或者p标签中获取文本。
  获取属性:
  使用attr()函数,以我们之前获取的li标签为例,获取其中的id属性
  # 获取 id 属性的方法<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_spec_id = li_spec.attr('id')
li_spec_id_2 = li_spec.attr.id
li_spec_id_3 = li_spec.attr['id']
  获取文本:
  使用text()函数, 以我们之前得到的p标签为例,获取其中的文本。
  string = p_tag.text()
  到此,在爬虫中会使用到的函数就是这些了。
  3、小结
  pyquery 还拥有操作文档树的能力,本篇文章着重介绍与爬虫相关的知识,所以就不再此详细叙述了,有兴趣的同学移步官方文档:
  最后,既然我们都分析了简书首页,请大家根据所学内容爬取简书首页所有的文章标题和文章链接,然后打印出来吧,像下图一样
  
  在公众号(Crossin的编程教室)里回复 pyquery,可获取本文的完整示例代码。
  『码上行动』在线学习班正在开放中,详情回复码上行动 查看全部

  【编程课堂】以 jQuery 之名 - 爬虫利器 PyQuery
  
  根据 id 定位找到这个li标签,代码如下:
  # 定位 id = note-11772642 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />pq_id = pq('#note-11772642')
  以上代码获取id名为note-11772642的标签,需要注意的是查询 id 时添加#前缀,这是 css 选择器语法。
  根据 class 定位:
  同样以刚才的为例
  
  我们根据class=have-img去获取这个li标签
  # 定位 class = have-img 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />pq_class = pq('.have-img')
  注意的是查询class时添加.前缀,这也是 css 选择器语法。
  2.3 索引标签
  在上一节的最后有个小问题,我们知道head标签在 html 中只有一个,而class名为have-img的li标签可能有多个,我们该
  如何遍历所有的li标签呢? 又该如何单独的取某一个li呢?
  首先我们可以逐个遍历
  # 遍历所有 class = have-img 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />for li in pq_class:    <br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />    # 获取每一个 li 标签
   pq_li = pq(li)
  我们可以索引某一个li标签
  使用.ep(index)函数。
  # 获取第一个 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_first = pq_class.ep(0)<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" /># 获取第二个 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_second = pq_class.ep(1)
  2.4 寻找标签
  同样回到刚刚的那张图
  
  在上一步,我们已经找到了所有的li标签,也知道如何取索引其中的元素,但我们现在要准确定位到某一个元素,比如上图中id = note-11772642这个li标签。
  这时候filter(selecter)就派上了用场
  li_spec = pq_class.filter('#note-11772642')
  这样我们就找到了指定的这个li标签,需要注意的是,filter函数只能在同一级标签中寻找,比如在这里只能过滤li标签,而不能定位li标签下的a标签、div标签等。
  当然,针对这种情况, pyquery 为我们提供了另外一个函数find(selector),该函数用于寻找子节点,继续以上图为例,寻找该特定 li 标签下的 p 标签
  p_tag = li_spec.find('p')
  2.5 提取属性与值
  以上我们讲了许多关于标签的知识,现在来谈谈怎么获取标签内的属性和标签包裹的文本,实际的爬虫项目中,通常这是最重要的一步,比如从a标签中获取链接、从li标签或者p标签中获取文本。
  获取属性:
  使用attr()函数,以我们之前获取的li标签为例,获取其中的id属性
  # 获取 id 属性的方法<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_spec_id = li_spec.attr('id')
li_spec_id_2 = li_spec.attr.id
li_spec_id_3 = li_spec.attr['id']
  获取文本:
  使用text()函数, 以我们之前得到的p标签为例,获取其中的文本。
  string = p_tag.text()
  到此,在爬虫中会使用到的函数就是这些了。
  3、小结
  pyquery 还拥有操作文档树的能力,本篇文章着重介绍与爬虫相关的知识,所以就不再此详细叙述了,有兴趣的同学移步官方文档:
  最后,既然我们都分析了简书首页,请大家根据所学内容爬取简书首页所有的文章标题和文章链接,然后打印出来吧,像下图一样
  
  在公众号(Crossin的编程教室)里回复 pyquery,可获取本文的完整示例代码。
  『码上行动』在线学习班正在开放中,详情回复码上行动

Taro + 小程序云开发实战|日语用例助手

网站优化优采云 发表了文章 • 0 个评论 • 110 次浏览 • 2022-05-05 15:05 • 来自相关话题

  Taro + 小程序云开发实战|日语用例助手
  前言
  小程序开放了云开发能力,为开发者提供了一个可以很快速构建小程序后端服务的能力,作为一名对新技术不倒腾不快的前端,对此也是很感兴趣的。
  Taro 是凹凸实验室推出的,基于React 语法规范的多端开发解决方案,较之于mpvue或者wepy,由于年轻,坑还比较多,但是很适合我这种倾向用React 开发的人。
  我结合这两者,使用cheerio和superagent 抓取了用例.jp, 开发了一个《日语用例助手》。
  入门踩坑1.云开发篇1.1 环境搭建
  云开发可以通过下列两种方式创建:1.使用quickstart(云开发快速启动模版)创建项目:
  
  这种方式会在目录下同时创建名为miniprogram ,带有云开发调用范例的小程序基础模板和名为cloudfuntions 的存放云函数的目录, 由此即可开始全新的项目。
  2.基于现有的小程序使用云开发:
  <p>在小程序目录下创建一个文件夹作为你的云函数目录,然后在project.config.json 文件中新增字段"cloudfunctionRoot": "你的云函数目录",即可以在微信开发者工具中看到目录的图标变成了云,在此目录下创建云函数即可;</p>
  
  1.2 云函数编写
  使用微信开发者工具在云函数目录下创建一个云函数时,会根据名称创建一个目录,目录中包含一个index.js 和package.json。
  在小程序中使用如下方式调用云函数:
  <p>wx.cloud.callFunction({
   name: '云函数名称',
   data: {
   key1: 'value1',
   key2: 'value2'
   }
  }).then((res) => {
   console.log(res);
  }).catch((e) => {
   console.log(e);
  });</p>
  index.js的入口函数如下所示:
  <p>//云函数入口函数
  exports.main = async (event, context) => {
   // 参数获取在event 中获取,如使用上面的调用函数后,获取data使用 event.key1、event.key2即可
   const { key1, key2 } = event;
   return { query: { key1, key2 } }
  }</p>
  每个云函数可视为一个单独的服务,如果需要安装第三方依赖,只需要在该目录点击右键,选择 在终端中打开, 并 npm install依赖即可。
  需要注意的是,每个云函数都是独立的,所需要的依赖都需要在对应的目录下进行 npm install,但这样就会使得项目变得十分庞大且不优雅。因此,接下来我介绍一下tcb-router。
  1.3 使用tcb-router管理路由
  tcb-router 是腾讯云团队开发的,基于 koa 风格的小程序·云开发云函数轻量级类路由库,主要用于优化服务端函数处理逻辑。
  使用tcb-router的方法很简单:
  <p>const TcbRouter = require('tcb-router');
  exports.main = (event, context) => {
   const app = new TcbRouter({ event });
   app.router('路由名称', async (ctx) => {
   //原有的event需要通过ctx._req.event 获取
   const { param1, param2 } = ctx._req.event;
   ctx.body = { key1: value1 };
   });
  })</p>
  此时小程序的调用方式也需要改成:
  <p>wx.cloud.callFunction({
   name: '云函数名称',
   data: {
   $url: '路由名称',
   // 其他数据
   param1: 'test1',
   param2: 'test2'
   },
   success: res => {},
   fail: err => {
   console.error(`[云函数] [${action}] 调用失败`, err)
   }
  })</p>
  2.Taro篇2.1 环境搭建
  <p>npm install -g @tarojs/cli
  taro init myApp</p>
  2.2 遇到的坑1.API支持不足
  由于Taro 对微信的一些新api 并没有支持到,比如使用云开发时需要用到 wx.cloud,Taro 并没有支持,但亲测是可以直接使用 wx 变量,但是会被eslint 提醒,看着十分不悦,可以在 .eslintrc 文件中增加以下代码:
  2.不能使用 Array#map 之外的方法操作 JSX 数组。
  3.不允许在 JSX 参数(props)中传入 JSX 元素(taro/no-jsx-in-props)。
  3.爬虫篇3.1 superagent
  superagent 是一个非常实用的http请求模块,用来抓取网页十分有用,使用也十分简单,以下是我在抓取 yourei.jp 时使用的代码:
  <p>// const superagent = require('superagent');
  // ...
  function crawler(url, cb) {
   return new Promise((resolve, reject) => {
   superagent.get(url).set({
   'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
   }).end(function (err, res) {
   if (err) {
   reject(err);
   return;
   }
   resolve(res);
   });
   });
  }</p>
  3.2 cheerio
  cheerio 是一个轻型灵活,类jQuery的对HTML元素分析操作的工具。在进行一些server端渲染的页面以及一些简单的小页面的爬取时,cheerio十分好用且高效。
  在使用 superagent 抓取了网页内容后,可以使用如下方式解析页面代码:
  <p> // const cheerio = require('cheerio');
   // ...
   const result = crawler(apiUrl).then((res) => {
   // 使用load 之后,$ 即可同jquery 一样使用选择器来选择元素了
   const $ = cheerio.load(res.text);
   const categories = [];
   $('[data-toggle]').each((i, ele) => {
   // 可以使用.text()、.html() 等方式获取元素的内容
   categories.push($(ele).attr('href'));
   });
   return {
   list: categories,
   };
   });</p>
  总结1.Taro
  如果你是React 开发者,需要开发多端小程序,或者原有React 项目想迁移到小程序,Taro 是个不错的选择,但还有很多坑没有填好,希望它的发展越来越好。
  2.云开发
  如果你是个人开发者,想尝试小程序开发又不想或者难以自己搭建服务器,云开发是个好选择,容易上手且十分敏捷。 查看全部

  Taro + 小程序云开发实战|日语用例助手
  前言
  小程序开放了云开发能力,为开发者提供了一个可以很快速构建小程序后端服务的能力,作为一名对新技术不倒腾不快的前端,对此也是很感兴趣的。
  Taro 是凹凸实验室推出的,基于React 语法规范的多端开发解决方案,较之于mpvue或者wepy,由于年轻,坑还比较多,但是很适合我这种倾向用React 开发的人。
  我结合这两者,使用cheerio和superagent 抓取了用例.jp, 开发了一个《日语用例助手》。
  入门踩坑1.云开发篇1.1 环境搭建
  云开发可以通过下列两种方式创建:1.使用quickstart(云开发快速启动模版)创建项目:
  
  这种方式会在目录下同时创建名为miniprogram ,带有云开发调用范例的小程序基础模板和名为cloudfuntions 的存放云函数的目录, 由此即可开始全新的项目。
  2.基于现有的小程序使用云开发:
  <p>在小程序目录下创建一个文件夹作为你的云函数目录,然后在project.config.json 文件中新增字段"cloudfunctionRoot": "你的云函数目录",即可以在微信开发者工具中看到目录的图标变成了云,在此目录下创建云函数即可;</p>
  
  1.2 云函数编写
  使用微信开发者工具在云函数目录下创建一个云函数时,会根据名称创建一个目录,目录中包含一个index.js 和package.json。
  在小程序中使用如下方式调用云函数:
  <p>wx.cloud.callFunction({
   name: '云函数名称',
   data: {
   key1: 'value1',
   key2: 'value2'
   }
  }).then((res) => {
   console.log(res);
  }).catch((e) => {
   console.log(e);
  });</p>
  index.js的入口函数如下所示:
  <p>//云函数入口函数
  exports.main = async (event, context) => {
   // 参数获取在event 中获取,如使用上面的调用函数后,获取data使用 event.key1、event.key2即可
   const { key1, key2 } = event;
   return { query: { key1, key2 } }
  }</p>
  每个云函数可视为一个单独的服务,如果需要安装第三方依赖,只需要在该目录点击右键,选择 在终端中打开, 并 npm install依赖即可。
  需要注意的是,每个云函数都是独立的,所需要的依赖都需要在对应的目录下进行 npm install,但这样就会使得项目变得十分庞大且不优雅。因此,接下来我介绍一下tcb-router。
  1.3 使用tcb-router管理路由
  tcb-router 是腾讯云团队开发的,基于 koa 风格的小程序·云开发云函数轻量级类路由库,主要用于优化服务端函数处理逻辑。
  使用tcb-router的方法很简单:
  <p>const TcbRouter = require('tcb-router');
  exports.main = (event, context) => {
   const app = new TcbRouter({ event });
   app.router('路由名称', async (ctx) => {
   //原有的event需要通过ctx._req.event 获取
   const { param1, param2 } = ctx._req.event;
   ctx.body = { key1: value1 };
   });
  })</p>
  此时小程序的调用方式也需要改成:
  <p>wx.cloud.callFunction({
   name: '云函数名称',
   data: {
   $url: '路由名称',
   // 其他数据
   param1: 'test1',
   param2: 'test2'
   },
   success: res => {},
   fail: err => {
   console.error(`[云函数] [${action}] 调用失败`, err)
   }
  })</p>
  2.Taro篇2.1 环境搭建
  <p>npm install -g @tarojs/cli
  taro init myApp</p>
  2.2 遇到的坑1.API支持不足
  由于Taro 对微信的一些新api 并没有支持到,比如使用云开发时需要用到 wx.cloud,Taro 并没有支持,但亲测是可以直接使用 wx 变量,但是会被eslint 提醒,看着十分不悦,可以在 .eslintrc 文件中增加以下代码:
  2.不能使用 Array#map 之外的方法操作 JSX 数组。
  3.不允许在 JSX 参数(props)中传入 JSX 元素(taro/no-jsx-in-props)。
  3.爬虫篇3.1 superagent
  superagent 是一个非常实用的http请求模块,用来抓取网页十分有用,使用也十分简单,以下是我在抓取 yourei.jp 时使用的代码:
  <p>// const superagent = require('superagent');
  // ...
  function crawler(url, cb) {
   return new Promise((resolve, reject) => {
   superagent.get(url).set({
   'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
   }).end(function (err, res) {
   if (err) {
   reject(err);
   return;
   }
   resolve(res);
   });
   });
  }</p>
  3.2 cheerio
  cheerio 是一个轻型灵活,类jQuery的对HTML元素分析操作的工具。在进行一些server端渲染的页面以及一些简单的小页面的爬取时,cheerio十分好用且高效。
  在使用 superagent 抓取了网页内容后,可以使用如下方式解析页面代码:
  <p> // const cheerio = require('cheerio');
   // ...
   const result = crawler(apiUrl).then((res) => {
   // 使用load 之后,$ 即可同jquery 一样使用选择器来选择元素了
   const $ = cheerio.load(res.text);
   const categories = [];
   $('[data-toggle]').each((i, ele) => {
   // 可以使用.text()、.html() 等方式获取元素的内容
   categories.push($(ele).attr('href'));
   });
   return {
   list: categories,
   };
   });</p>
  总结1.Taro
  如果你是React 开发者,需要开发多端小程序,或者原有React 项目想迁移到小程序,Taro 是个不错的选择,但还有很多坑没有填好,希望它的发展越来越好。
  2.云开发
  如果你是个人开发者,想尝试小程序开发又不想或者难以自己搭建服务器,云开发是个好选择,容易上手且十分敏捷。

Java做爬虫也很牛

网站优化优采云 发表了文章 • 0 个评论 • 98 次浏览 • 2022-05-05 15:00 • 来自相关话题

  Java做爬虫也很牛
  工具类实现比较简单,就一个get方法,读取请求地址的响应内容,这边我们用来抓取网页的内容,这边没有用代理,在真正的抓取过程中,当你大量请求某个网站的时候,对方会有一系列的策略来禁用你的请求,这个时候代理就排上用场了,通过代理设置不同的IP来抓取数据。
  import java.io.BufferedReader;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.io.InputStreamReader;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.net.HttpURLConnection;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.net.URL;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />public class HttpUtils {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static String get(String url) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        try {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            URL getUrl = new URL(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            HttpURLConnection connection = (HttpURLConnection) getUrl<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    .openConnection();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestMethod("GET");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestProperty("Accept", "*/*");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    .setRequestProperty("User-Agent",<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA)");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestProperty("Accept-Language", "zh-cn");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.connect();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            String line;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            StringBuffer result = new StringBuffer();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            while ((line = reader.readLine()) != null){<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                result.append(line);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            reader.close();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            return result.toString();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        } catch (Exception e) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            e.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        return null;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  接下来我们随便找一个有图片的网页,来试试抓取功能
  public static void main(String[] args) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List imgUrls = getImageSrc(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (String imgSrc : imgUrls) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            System.out.println(imgSrc);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static List getImageSrc(String html) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        // 获取img标签正则<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String IMGURL_REG = "]*?>";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        // 获取src路径的正则<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String IMGSRC_REG = "http:\"?(.*?)(\"|>|\\s+)";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Matcher matcher = Pattern.compile(IMGURL_REG).matcher(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List listImgUrl = new ArrayList();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        while (matcher.find()) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Matcher m = Pattern.compile(IMGSRC_REG).matcher(matcher.group());<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            while (m.find()) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                listImgUrl.add(m.group().substring(0, m.group().length() - 1));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        return listImgUrl;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  首先将网页的内容抓取下来,然后用正则的方式解析出网页的标签,再解析img的地址。执行程序我们可以得到下面的内容:
  http://p9.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p1.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p3.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p1.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p3.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  通过上面的地址我们就可以将图片下载到本地了,下面我们写个图片下载的方法:
  public static void main(String[] args) throws MalformedURLException, IOException {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List imgUrls = getImageSrc(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (String imgSrc : imgUrls) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  这样就很简单的实现了一个抓取并且提取图片的功能了,看起来还是比较麻烦哈,要写正则之类的 ,下面给大家介绍一种更简单的方式,如果你熟悉jQuery的话对提取元素就很简单了,这个框架就是Jsoup。
  jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
  添加jsoup的依赖:
  <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  org.jsoup<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  jsoup<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  1.11.3<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  使用jsoup之后提取的代码只需要简单的几行即可:
  public static void main(String[] args) throws MalformedURLException, IOException {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Document doc = Jsoup.parse(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Elements imgs = doc.getElementsByTag("img");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (Element img : imgs) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            String imgSrc = img.attr("src");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            if (imgSrc.startsWith("//")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                imgSrc = "http:" + imgSrc;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  通过Jsoup.parse创建一个文档对象,然后通过getElementsByTag的方法提取出所有的图片标签,循环遍历,通过attr方法获取图片的src属性,然后下载图片。
  Jsoup使用起来非常简单,当然还有很多其他解析网页的操作,大家可以去看看资料学习一下。
  下面我们再来升级一下,做成一个小工具,提供一个简单的界面,输入一个网页地址,点击提取按钮,然后把图片自动下载下来,我们可以用swing写界面。
  public class App {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static void main(String[] args) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JFrame frame = new JFrame();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setResizable(false);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setSize(425,400);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setLayout(null);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setLocationRelativeTo(null);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JTextField jTextField = new JTextField();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jTextField.setBounds(100, 44, 200, 30);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.add(jTextField);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JButton jButton = new JButton("提取");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jButton.setBounds(140, 144, 100, 30);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.add(jButton);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setVisible(true);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jButton.addActionListener(new ActionListener() {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            @Override<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            public void actionPerformed(ActionEvent e) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                String url = jTextField.getText();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                if (url == null || url.equals("")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    JOptionPane.showMessageDialog(null, "请填写抓取地址");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    return;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                Document doc = Jsoup.parse(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                Elements imgs = doc.getElementsByTag("img");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                for (Element img : imgs) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    String imgSrc = img.attr("src");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    if (imgSrc.startsWith("//")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        imgSrc = "http:" + imgSrc;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    try {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    } catch (MalformedURLException e1) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        e1.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    } catch (IOException e1) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        e1.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                JOptionPane.showMessageDialog(null, "抓取完成");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        });<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  执行main方法首先出来的就是我们的界面了,如下:
  
  屏幕快照 2018-06-18 09.50.34 PM.png
  输入地址,点击提取按钮即可下载图片。
  特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:
  
  <p class="" style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;">长按订阅更多精彩▼
  
  如有收获,点个在看,诚挚感谢</p> 查看全部

  Java做爬虫也很牛
  工具类实现比较简单,就一个get方法,读取请求地址的响应内容,这边我们用来抓取网页的内容,这边没有用代理,在真正的抓取过程中,当你大量请求某个网站的时候,对方会有一系列的策略来禁用你的请求,这个时候代理就排上用场了,通过代理设置不同的IP来抓取数据。
  import java.io.BufferedReader;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.io.InputStreamReader;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.net.HttpURLConnection;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.net.URL;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />public class HttpUtils {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static String get(String url) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        try {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            URL getUrl = new URL(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            HttpURLConnection connection = (HttpURLConnection) getUrl<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    .openConnection();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestMethod("GET");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestProperty("Accept", "*/*");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    .setRequestProperty("User-Agent",<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA)");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestProperty("Accept-Language", "zh-cn");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.connect();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            String line;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            StringBuffer result = new StringBuffer();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            while ((line = reader.readLine()) != null){<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                result.append(line);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            reader.close();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            return result.toString();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        } catch (Exception e) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            e.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        return null;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  接下来我们随便找一个有图片的网页,来试试抓取功能
  public static void main(String[] args) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List imgUrls = getImageSrc(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (String imgSrc : imgUrls) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            System.out.println(imgSrc);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static List getImageSrc(String html) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        // 获取img标签正则<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String IMGURL_REG = "]*?>";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        // 获取src路径的正则<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String IMGSRC_REG = "http:\"?(.*?)(\"|>|\\s+)";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Matcher matcher = Pattern.compile(IMGURL_REG).matcher(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List listImgUrl = new ArrayList();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        while (matcher.find()) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Matcher m = Pattern.compile(IMGSRC_REG).matcher(matcher.group());<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            while (m.find()) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                listImgUrl.add(m.group().substring(0, m.group().length() - 1));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        return listImgUrl;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  首先将网页的内容抓取下来,然后用正则的方式解析出网页的标签,再解析img的地址。执行程序我们可以得到下面的内容:
  http://p9.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p1.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p3.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p1.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p3.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  通过上面的地址我们就可以将图片下载到本地了,下面我们写个图片下载的方法:
  public static void main(String[] args) throws MalformedURLException, IOException {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List imgUrls = getImageSrc(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (String imgSrc : imgUrls) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  这样就很简单的实现了一个抓取并且提取图片的功能了,看起来还是比较麻烦哈,要写正则之类的 ,下面给大家介绍一种更简单的方式,如果你熟悉jQuery的话对提取元素就很简单了,这个框架就是Jsoup。
  jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
  添加jsoup的依赖:
  <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  org.jsoup<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  jsoup<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  1.11.3<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  使用jsoup之后提取的代码只需要简单的几行即可:
  public static void main(String[] args) throws MalformedURLException, IOException {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Document doc = Jsoup.parse(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Elements imgs = doc.getElementsByTag("img");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (Element img : imgs) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            String imgSrc = img.attr("src");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            if (imgSrc.startsWith("//")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                imgSrc = "http:" + imgSrc;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  通过Jsoup.parse创建一个文档对象,然后通过getElementsByTag的方法提取出所有的图片标签,循环遍历,通过attr方法获取图片的src属性,然后下载图片。
  Jsoup使用起来非常简单,当然还有很多其他解析网页的操作,大家可以去看看资料学习一下。
  下面我们再来升级一下,做成一个小工具,提供一个简单的界面,输入一个网页地址,点击提取按钮,然后把图片自动下载下来,我们可以用swing写界面。
  public class App {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static void main(String[] args) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JFrame frame = new JFrame();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setResizable(false);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setSize(425,400);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setLayout(null);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setLocationRelativeTo(null);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JTextField jTextField = new JTextField();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jTextField.setBounds(100, 44, 200, 30);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.add(jTextField);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JButton jButton = new JButton("提取");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jButton.setBounds(140, 144, 100, 30);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.add(jButton);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setVisible(true);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jButton.addActionListener(new ActionListener() {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            @Override<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            public void actionPerformed(ActionEvent e) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                String url = jTextField.getText();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                if (url == null || url.equals("")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    JOptionPane.showMessageDialog(null, "请填写抓取地址");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    return;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                Document doc = Jsoup.parse(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                Elements imgs = doc.getElementsByTag("img");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                for (Element img : imgs) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    String imgSrc = img.attr("src");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    if (imgSrc.startsWith("//")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        imgSrc = "http:" + imgSrc;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    try {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    } catch (MalformedURLException e1) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        e1.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    } catch (IOException e1) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        e1.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                JOptionPane.showMessageDialog(null, "抓取完成");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        });<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  执行main方法首先出来的就是我们的界面了,如下:
  
  屏幕快照 2018-06-18 09.50.34 PM.png
  输入地址,点击提取按钮即可下载图片。
  特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:
  
  <p class="" style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;">长按订阅更多精彩▼
  
  如有收获,点个在看,诚挚感谢</p>

jquery抓取网页内容(我有一个包含html和文本的文本区域,我想抓取它们)

网站优化优采云 发表了文章 • 0 个评论 • 70 次浏览 • 2022-04-18 02:33 • 来自相关话题

  jquery抓取网页内容(我有一个包含html和文本的文本区域,我想抓取它们)
  我有一个收录 html 和文本的 textarea,我想从 textarea 中获取它们,但这样做似乎只能得到 html 代码而不是文本
  HTML 代码
  

<br />

<br />
Ormai sono più di 3 mesi che ho iniziato a fotografare in studio. (Per studio intendo "stanza" dove mi cemento in esperimenti fotografici :P)<br />
Il concetto principalemente rimane lo stesso, ma riuscire a controllare le luci, riflessi e gradienti è diventata quasi la mia sfida quotidiana!<br />
<br />
Ci tengo a precisare che la mia passione rimane sempre la fotografia paesaggistica, purtroppo però ho il vizio di non accontentarmi ma mai e ricerco sempre location che purtroppo non sono alla portata del viaggiatore del "week-end"<br />
<br />
In studio mi cimento spesso nell&#39; action freezing, ovvero nel congelare un movimento, che sia di liquidi o polveri.<br />
<br />
In questo caso ho usato del colorante marrone per cibo, ne ho fatto una pentola intera! La cosa essenziale è il movimento con cui realizzi lo splash...ogni movimento forma uno "shape" diverso. Spesso cambio anche contenitore...<br />
<br />
Le parti in porcellana le ho fotografate tutte singolarmente in modo da poter controllare luce, colore e gradiente.<br />
<br />
La sfida più grande è stata riuscire a fotografare il cucchiaino in acciaio. Notoriamente il metallo è riflettente e se aggiungiamo la parte concava del cucchiaio, beh, riflessi a gogo!<br />
Per ottenere un immagine prima di riflessi, in commercio ci sono dei Light Box, ovvero delle scatole formate da pareti semi trasparenti che permettono di collocare 4 o più luci estremamente, ottenendo oggetti illuminati perfettamente e senza riflessi esterni.<br />
...purtroppo io ancora non ce l&#39;ho...ed ho dovuto affidarmi al mio grande amico photoshop... e meno male che esiste! :D<br />
<br />
Una volta ottenuto tutte le parti, ed aver selezionato la splash migliore, ho unito il tutto sempre su PS.<br />
<br />
Spero che questo post sia di ispirazione!<br />
<br />
Pat.<br />
<br />
  JQUERY 代码
  $(function(){
var pcontent = $(&#39;#post&#39;).val(),
content = $($(&#39;#post&#39;).val());
console.log(content.html());
});
  这是 Jsfiddle 上用于输出的实时预览
  最佳答案
  您可以在 JQuery 中使用 .val() 直接获取这两个。
  试试这个:
  $(function(){
var pcontent = $(&#39;textarea#post&#39;).val();
console.log(pcontent);
})
  关于 javascript - 使用 jQuery 抓取文本区域内容,我们在 Stack Overflow 上发现了一个类似的问题: 查看全部

  jquery抓取网页内容(我有一个包含html和文本的文本区域,我想抓取它们)
  我有一个收录 html 和文本的 textarea,我想从 textarea 中获取它们,但这样做似乎只能得到 html 代码而不是文本
  HTML 代码
  

<br />

<br />
Ormai sono più di 3 mesi che ho iniziato a fotografare in studio. (Per studio intendo "stanza" dove mi cemento in esperimenti fotografici :P)<br />
Il concetto principalemente rimane lo stesso, ma riuscire a controllare le luci, riflessi e gradienti è diventata quasi la mia sfida quotidiana!<br />
<br />
Ci tengo a precisare che la mia passione rimane sempre la fotografia paesaggistica, purtroppo però ho il vizio di non accontentarmi ma mai e ricerco sempre location che purtroppo non sono alla portata del viaggiatore del "week-end"<br />
<br />
In studio mi cimento spesso nell&#39; action freezing, ovvero nel congelare un movimento, che sia di liquidi o polveri.<br />
<br />
In questo caso ho usato del colorante marrone per cibo, ne ho fatto una pentola intera! La cosa essenziale è il movimento con cui realizzi lo splash...ogni movimento forma uno "shape" diverso. Spesso cambio anche contenitore...<br />
<br />
Le parti in porcellana le ho fotografate tutte singolarmente in modo da poter controllare luce, colore e gradiente.<br />
<br />
La sfida più grande è stata riuscire a fotografare il cucchiaino in acciaio. Notoriamente il metallo è riflettente e se aggiungiamo la parte concava del cucchiaio, beh, riflessi a gogo!<br />
Per ottenere un immagine prima di riflessi, in commercio ci sono dei Light Box, ovvero delle scatole formate da pareti semi trasparenti che permettono di collocare 4 o più luci estremamente, ottenendo oggetti illuminati perfettamente e senza riflessi esterni.<br />
...purtroppo io ancora non ce l&#39;ho...ed ho dovuto affidarmi al mio grande amico photoshop... e meno male che esiste! :D<br />
<br />
Una volta ottenuto tutte le parti, ed aver selezionato la splash migliore, ho unito il tutto sempre su PS.<br />
<br />
Spero che questo post sia di ispirazione!<br />
<br />
Pat.<br />
<br />
  JQUERY 代码
  $(function(){
var pcontent = $(&#39;#post&#39;).val(),
content = $($(&#39;#post&#39;).val());
console.log(content.html());
});
  这是 Jsfiddle 上用于输出的实时预览
  最佳答案
  您可以在 JQuery 中使用 .val() 直接获取这两个。
  试试这个:
  $(function(){
var pcontent = $(&#39;textarea#post&#39;).val();
console.log(pcontent);
})
  关于 javascript - 使用 jQuery 抓取文本区域内容,我们在 Stack Overflow 上发现了一个类似的问题:

jquery抓取网页内容(如何让一个使用框架的网页为主要搜索引擎正确索引及如何进行优化)

网站优化优采云 发表了文章 • 0 个评论 • 61 次浏览 • 2022-04-16 00:33 • 来自相关话题

  jquery抓取网页内容(如何让一个使用框架的网页为主要搜索引擎正确索引及如何进行优化)
  谷歌开始抓取框架内容。过去很多人不相信这一点,但随着GOOGLE阅读和爬虫技术的不断深入
  发展,今天是完全可能的事情!
  什么是框架页面?
  是使用一种实现来调用其他 网站/ 页面
  当您浏览收录此内容的页面 A 时,您会看到页面 B
  论框架网页的优化技巧
  从一开始,构建 网站 就对专业的 SEO 来说也是一个挑战。是否使用框架技术来设计新的网页也成为争论的话题。在这个文章中,我们为您提供了一些基本的优化技术,同时您可以学习如何让框架页面正确索引到主要搜索引擎以及如何优化它。
  首先,我们来看看网站使用框架设计的好处。它的优越性体现在对整个网页设计完整性的维护和更新上。这就是为什么有不少网站设计师更喜欢使用框架技术进行网站设计的原因。尤其是大型网站(至少500页以上),使用框架可以让网站的维护相对容易。
  什么是框架网页?
  如果一个网页的左侧导航菜单是固定的,而页面中间的信息可以上下移动,那么一般可以认为是一个带框的网页。此外,一些带框的网站模板在其页面顶部有公司的徽标或图像。但是,这块也是固定的。页面的其余部分可以上下左右移动。一些框架站点模板还在其固定区域放置链接或导航按钮。另外,在加框的网页中,深层页面的域名通常不会反映在 URL 中(这意味着在浏览器的 URL 栏中,不会显示您当前正在查看的深层页面,而是主页)。
  在一般结构的网站中不存在这种问题。
  您可以阅读很多关于 SEO 的 文章,无论是在好书还是在网上。在这些文章中,基本认为网站用框架来设计是极其不可取的。这是因为大多数搜索引擎无法识别网页中的框架,或者无法遍历或搜索框架中的内容。
  在这种情况下,其他人可能会告诉您,使用框架的 网站 永远无法被搜索引擎索引并且无法很好地优化。这个论点好坏参半。如果框架使用得当,这个论点是站不住脚的。但是对于框架的错误使用,或者网站的设计没有考虑到当今搜索引擎技术的方方面面,那么这句话还是有些道理的。 查看全部

  jquery抓取网页内容(如何让一个使用框架的网页为主要搜索引擎正确索引及如何进行优化)
  谷歌开始抓取框架内容。过去很多人不相信这一点,但随着GOOGLE阅读和爬虫技术的不断深入
  发展,今天是完全可能的事情!
  什么是框架页面?
  是使用一种实现来调用其他 网站/ 页面
  当您浏览收录此内容的页面 A 时,您会看到页面 B
  论框架网页的优化技巧
  从一开始,构建 网站 就对专业的 SEO 来说也是一个挑战。是否使用框架技术来设计新的网页也成为争论的话题。在这个文章中,我们为您提供了一些基本的优化技术,同时您可以学习如何让框架页面正确索引到主要搜索引擎以及如何优化它。
  首先,我们来看看网站使用框架设计的好处。它的优越性体现在对整个网页设计完整性的维护和更新上。这就是为什么有不少网站设计师更喜欢使用框架技术进行网站设计的原因。尤其是大型网站(至少500页以上),使用框架可以让网站的维护相对容易。
  什么是框架网页?
  如果一个网页的左侧导航菜单是固定的,而页面中间的信息可以上下移动,那么一般可以认为是一个带框的网页。此外,一些带框的网站模板在其页面顶部有公司的徽标或图像。但是,这块也是固定的。页面的其余部分可以上下左右移动。一些框架站点模板还在其固定区域放置链接或导航按钮。另外,在加框的网页中,深层页面的域名通常不会反映在 URL 中(这意味着在浏览器的 URL 栏中,不会显示您当前正在查看的深层页面,而是主页)。
  在一般结构的网站中不存在这种问题。
  您可以阅读很多关于 SEO 的 文章,无论是在好书还是在网上。在这些文章中,基本认为网站用框架来设计是极其不可取的。这是因为大多数搜索引擎无法识别网页中的框架,或者无法遍历或搜索框架中的内容。
  在这种情况下,其他人可能会告诉您,使用框架的 网站 永远无法被搜索引擎索引并且无法很好地优化。这个论点好坏参半。如果框架使用得当,这个论点是站不住脚的。但是对于框架的错误使用,或者网站的设计没有考虑到当今搜索引擎技术的方方面面,那么这句话还是有些道理的。

jquery抓取网页内容(我的个人博客技术栈变更与我感受中的前端技术发展)

网站优化优采云 发表了文章 • 0 个评论 • 49 次浏览 • 2022-04-14 13:31 • 来自相关话题

  jquery抓取网页内容(我的个人博客技术栈变更与我感受中的前端技术发展)
  概述
  这次的标题非常抢眼。这个文章其实是想谈谈我个人博客的技术栈的变化以及我的感受中的前端技术的发展。
  事实上,对我来说,博客这个词似乎是上个世纪的事情。小时候微博很流行。我是在微博之后才知道写博客的。2017年左右,突然想找个地方输出文字,做一些记录。当时我注册了一个微信公众号,直到2019年才开始搭建这个个人博客。其实建博客可以说是酒鬼不喝酒的本意。成熟的博客生成应用相当多,不用自己折腾。但是当时我在宣传的时候买了一台阿里云服务器,只是想学习一些前端技术。这个博客是关于它应运而生的。
  有时是为了实现一些功能,学习一些新技术,有时恰恰相反,把一些新东西应用到博客上,使博客成为一个完整的“冗余项目”。我博客的技术栈发生了变化,也就是刚好成为我个人技术栈的成长过程,就在这里记录一下,顺便记录一下使用NextJS的心得。
  模板渲染、Session 和 jQuery
  一开始,作为一个主要使用Python的后端程序员,我尝试使用Django开发博客。Django 是一个遵循 MVC 模型的 Web 框架。Python相关的应用一般性能不强,所以Django的主要卖点是快速交付、内置用户系统、管理后台、模型迁移等。博客的初始版本没多久。完成。
  数据库使用 MySQL,在 Django 中使用内置的模板引擎来处理前端页面:
  {% if latest_question_list %}

{% for question in latest_question_list %}
{{ question.question_text }}
{% endfor %}

{% else %}
<p>No polls are available.
{% endif %}
</p>
  将静态文件放在约定的文件夹中,使用 nginx 代理。UI风格主要是通过BootStrap。毕竟我对CSS真的很陌生,有些页面动画也是通过框架或者搜索一些jQuery代码来解决的。这里有很多 Doucet 的博客。
  Django内置了用户和组模型,管理后台也内置。登录认证也是通过默认的Session中间件实现的,OAuth登录是通过第三方库实现的。基本上,没有时间花在这些方面。最开始博客开通了登录注册和评论功能可以通过Github登录,但是后来被认为没有必要的时候就删除了。这里 UI 和业务代码是完全紧密联系在一起的。
  RESTful、Docker 和 TLS
  由于工作原因,我开始向全栈方向发展,开始学习JavaScript。在此之前,我经常听到三个前端框架的名字。因为一不小心加了一个 React 组,就开始学习 React。这段时间,我先把博客的后端部分提取出来,并借助Django REST框架库快速完成了这部分工作,力图使接口符合RESTful规范。毕竟,应用程序很简单,没有什么可以妥协或违反规范的。注释 去掉了这个功能,但是仍然保留了登录界面,所以做了一个JWT登录认证界面,后来删掉了。Django 部分的其余部分不再关心如何呈现用户界面,
  我的服务器操作系统是 Ubuntu 18.04。在最初的部署过程中,我们需要考虑 Python 版本,以及 nginx 和 MySQL 的安装。如果以后需要迁移服务器(毕竟阿里云学生机活动才两年),也比较麻烦,所以我用了Docker,写好镜像文件后,运行容器。
  在安全问题和钱包的取舍中,​​我选择了 Let's Encypt 的免费证书来实现 HTTPS,安装简单,每三个月自动更新一次。
  SPA和SSR
  在项目中成功使用React作为管理后台后,开始考虑在博客中使用。但是通常都是开发SPA单页应用,怎么解决SEO问题呢?
  之前,我使用 Django 的模板引擎进行服务器端渲染,即在返回响应之前,我已经将 文章 内容和其他数据插入到 HTML 文件中,最终用户在浏览器中获取静态文件。如果用户请求到另一个页面,那么他会得到一个完全不同的静态文件。
  用 React 编写的 SPA 在客户端渲染,使用虚拟 DOM,整个应用程序往往只有一个 HTML 文件,切换页面不会重新请求新页面,而是替换需要更改的组件。
  那么两者的优劣势就很明显了。传统的服务器端渲染(SSR),首页打开速度更快,因为一次不会加载太多内容,对搜索引擎也很友好。毕竟爬虫可以直接获取到一个收录数据的静态 HTML 文件,但是切换页面需要替换整个页面并重新渲染,而且前后端、表现层和业务层是紧耦合的;单页应用在客户端渲染,页面切换快,数据异步获取,前后端分离,但由于首次访问获取整个应用资源,首屏加载慢,在客户端由JS渲染,爬虫很难获取到需要的数据,
  NextJS:页面、路由和自定义应用
  通过 React 和 SEO 这两个关键词,我发现了 NextJS,即 React 脚手架。在它的官网上,我看到了关键词SSR服务端渲染。前端经过多年的发展会倒退吗?当然不是,历史的发展总是螺旋式上升的,这里的SSR不同于传统的方式。准确的说,这个技术应该叫SSG静态站点生成或者Jamstack。
  NextJS 采用常规路由。pages目录下的文件名,如about.js,对应URL /about,默认导出的组件为页面组件。比较特别的是index.js对应的是/。除此之外,还有动态路由,它要求文件名用方括号括起来,例如 [tag].js。可以匹配/a、/someThing、/?tag=crumb等。 pages目录默认为页面级组件,共享组件放在src/component。
  框架提供了useRoute Hook,方便我们使用路由api。这里主要是希望在页面切换时监听切换事件,改变加载状态,改善弱网环境下的用户体验(其实很难看到这个切换过程,后面的原因又来了)。监听路由切换很方便,但是如果每个页面都需要注册一次监听,并且在组件卸载的时候取消监听,会出现太多重复的代码。
  NextJS 提供了修改容器组件的功能,在 pages 文件夹中新建一个 _app.js:
  // _app.tsx节选
function MyApp({ Component, pageProps }: AppProps) {
const [loading, setLoading] = useState(false)
const router = useRouter()
const startLoading = () => {
console.log(&#39;route change start&#39;)
setLoading(true)
}
const stopLoading = () => {
console.log(&#39;route change complete&#39;)
setLoading(false)
}
useEffect(() => {
router.events.on(&#39;routeChangeStart&#39;, startLoading)
router.events.on(&#39;routeChangeComplete&#39;, stopLoading)
router.events.on(&#39;routeChangeError&#39;, stopLoading)
return () => {
router.events.off(&#39;routeChangeStart&#39;, startLoading)
router.events.off(&#39;routeChangeComplete&#39;, stopLoading)
router.events.on(&#39;routeChangeError&#39;, stopLoading)
}
}, [])
return (





{`
body {
background-color: #f6f6f6
};
`}

)
}
  上面代码中使用了内置的css-in-component,一种内联样式的写法。我当时使用的 React 版本已经有了 Hooks。我在整个博客代码中使用了功能组件。其实这里也可以使用类组件。
  数据获取
  前面提到过,NextJS 允许搜索引擎获取预渲染的、带有数据的静态页面,那么如何在 Next 中获取数据呢?
  CI/CD、无服务器和 GraphQL
  一开始打算用Github Actions进行自动部署,但碰巧遇到了Next更新,而且Next所属的Vercel云服务比较好用,所以选择了官方推荐的方式,只要你提供一个链接到 git 仓库,Vercel 会在每次推送后自动以 serverless 的形式部署,并提供域名和 HTTPS 证书(其实就是 Let's Encypt 的证书)。
  此时,我想将后端转换为无服务器应用程序。顺便发现了hasura,它可以提供免费的GraphQL服务。只要有 postgresql 数据库,就可以生成基于 GraphQL 的后端。简单的CRUD完全没问题,所以没有继续折腾。但是对于前端,我只是想在构建过程中获取数据。Apollo 对我来说太重了,所以我找到了 graphql-request 库,它基本上只是对 fetch 的简单封装,足够使用 .
  // 示例
const response = await request(GraphQLEndpoint, query, variables)
  Link、Shallow Routing、Screening Paging 前面提到,服务器端渲染在切换页面的速度上存在缺陷,因为请求新页面需要返回新页面的完整静态文件,即使大部分页面布局没有改变了。Next 提供的 Link 组件,默认会在空闲时自动请求 JSON 数据,这样当用户点击链接时,可以快速改变内容,渲染新的页面。这也是因为我在非弱网络环境中看到了这一点。没有页面加载效果。
  在我的博客中,我为 文章 模型设置了很多外键,例如 文章 列、标签和分页。如果我想为这些设置页面,Next 提供了一种避免重新抓取的方法。浅路由,获取数据更新页面的方式:
  // 代码节选
route.push(`/posts?column=${item.column.name}`, undefined, { shallow: true })}>{item.column.name}
const route = useRoute()
useEffect(() => {
if (column) {
setArticles(articles => sourceArticles.filter(article => article.column.name === route.query.column))
}
console.log(articles)
}, [route.query.column])
  在useEffect的Hook中,根据route.query.column的变化判断是否更新文章数据源,过滤即可,无需重新取数据,并且页面仅部分更新。
  但是我很贪心,想用静态模式,每次只获取过滤需要的数据,而不是一次性获取所有数据,在客户端进行过滤,这个可以借助帮助动态路由的(这里我使用 TypeScript,Next 完全支持 TS):
  pages
├── about.tsx
├── _app.tsx
├── posts
│ └── [id].tsx
├── series.tsx
└── [column]
│ └── [page].tsx
├── [tag]
│ └── [page].tsx
└── [page].tsx
  但是这种形式,对栏目、标签、页面的过滤其实就是首页列表页,导致只有getStaticPaths函数不同,其余都是重复代码,不能接受,只有这样才可以接受 /[column]/[page 的路由,但不接受 /column=Python&amp;page=2 的查询形式。
  那么有没有办法一次接受所有的动态路由呢?其实有,一个叫[...slug]的页面组件就可以了,但是参数只能是数组,比如['a','b']对应/a/b,所以可以' t 区分Column和tag,并且如上所述,不能以查询参数的形式访问。
  在这方面,有一个问题。在某个版本中可以实现getStaticParams等API。对于博客等小数据的应用,使用 Shallow Routing 完全没问题,但对于 知乎 这样的大平台,过滤、搜索、分页都是必不可少的。
  下一步
  现在我博客原有的Django部分已经完全废弃了,自然不能使用Django提供的管理后台。Blazor在上一篇文章文章中介绍过,预计还要几个周末才能到。构建 SPA 后端。毕竟后端应用不需要SEO,SPA会更合适。CSharp 用于编写前端。过去,JS 渗透到桌面和移动端。反过来,静态语言开始蚕食 web 前端。
  总的来说,这个博客的不断重建过程,也是我学习一些前端技巧的一个实验过程。在这个过程中,我感觉自己经历了前端技术的发展变化。工程化、系统化,随着Node和一些框架的发展,前端开发体验也在不断提升。博客本身就变成了一个实验室,各种事情轮番经历。这个过程暂时不会停止。毕竟,业余时间写代码是很有趣的。博客已开源。 查看全部

  jquery抓取网页内容(我的个人博客技术栈变更与我感受中的前端技术发展)
  概述
  这次的标题非常抢眼。这个文章其实是想谈谈我个人博客的技术栈的变化以及我的感受中的前端技术的发展。
  事实上,对我来说,博客这个词似乎是上个世纪的事情。小时候微博很流行。我是在微博之后才知道写博客的。2017年左右,突然想找个地方输出文字,做一些记录。当时我注册了一个微信公众号,直到2019年才开始搭建这个个人博客。其实建博客可以说是酒鬼不喝酒的本意。成熟的博客生成应用相当多,不用自己折腾。但是当时我在宣传的时候买了一台阿里云服务器,只是想学习一些前端技术。这个博客是关于它应运而生的。
  有时是为了实现一些功能,学习一些新技术,有时恰恰相反,把一些新东西应用到博客上,使博客成为一个完整的“冗余项目”。我博客的技术栈发生了变化,也就是刚好成为我个人技术栈的成长过程,就在这里记录一下,顺便记录一下使用NextJS的心得。
  模板渲染、Session 和 jQuery
  一开始,作为一个主要使用Python的后端程序员,我尝试使用Django开发博客。Django 是一个遵循 MVC 模型的 Web 框架。Python相关的应用一般性能不强,所以Django的主要卖点是快速交付、内置用户系统、管理后台、模型迁移等。博客的初始版本没多久。完成。
  数据库使用 MySQL,在 Django 中使用内置的模板引擎来处理前端页面:
  {% if latest_question_list %}

{% for question in latest_question_list %}
{{ question.question_text }}
{% endfor %}

{% else %}
<p>No polls are available.
{% endif %}
</p>
  将静态文件放在约定的文件夹中,使用 nginx 代理。UI风格主要是通过BootStrap。毕竟我对CSS真的很陌生,有些页面动画也是通过框架或者搜索一些jQuery代码来解决的。这里有很多 Doucet 的博客。
  Django内置了用户和组模型,管理后台也内置。登录认证也是通过默认的Session中间件实现的,OAuth登录是通过第三方库实现的。基本上,没有时间花在这些方面。最开始博客开通了登录注册和评论功能可以通过Github登录,但是后来被认为没有必要的时候就删除了。这里 UI 和业务代码是完全紧密联系在一起的。
  RESTful、Docker 和 TLS
  由于工作原因,我开始向全栈方向发展,开始学习JavaScript。在此之前,我经常听到三个前端框架的名字。因为一不小心加了一个 React 组,就开始学习 React。这段时间,我先把博客的后端部分提取出来,并借助Django REST框架库快速完成了这部分工作,力图使接口符合RESTful规范。毕竟,应用程序很简单,没有什么可以妥协或违反规范的。注释 去掉了这个功能,但是仍然保留了登录界面,所以做了一个JWT登录认证界面,后来删掉了。Django 部分的其余部分不再关心如何呈现用户界面,
  我的服务器操作系统是 Ubuntu 18.04。在最初的部署过程中,我们需要考虑 Python 版本,以及 nginx 和 MySQL 的安装。如果以后需要迁移服务器(毕竟阿里云学生机活动才两年),也比较麻烦,所以我用了Docker,写好镜像文件后,运行容器。
  在安全问题和钱包的取舍中,​​我选择了 Let's Encypt 的免费证书来实现 HTTPS,安装简单,每三个月自动更新一次。
  SPA和SSR
  在项目中成功使用React作为管理后台后,开始考虑在博客中使用。但是通常都是开发SPA单页应用,怎么解决SEO问题呢?
  之前,我使用 Django 的模板引擎进行服务器端渲染,即在返回响应之前,我已经将 文章 内容和其他数据插入到 HTML 文件中,最终用户在浏览器中获取静态文件。如果用户请求到另一个页面,那么他会得到一个完全不同的静态文件。
  用 React 编写的 SPA 在客户端渲染,使用虚拟 DOM,整个应用程序往往只有一个 HTML 文件,切换页面不会重新请求新页面,而是替换需要更改的组件。
  那么两者的优劣势就很明显了。传统的服务器端渲染(SSR),首页打开速度更快,因为一次不会加载太多内容,对搜索引擎也很友好。毕竟爬虫可以直接获取到一个收录数据的静态 HTML 文件,但是切换页面需要替换整个页面并重新渲染,而且前后端、表现层和业务层是紧耦合的;单页应用在客户端渲染,页面切换快,数据异步获取,前后端分离,但由于首次访问获取整个应用资源,首屏加载慢,在客户端由JS渲染,爬虫很难获取到需要的数据,
  NextJS:页面、路由和自定义应用
  通过 React 和 SEO 这两个关键词,我发现了 NextJS,即 React 脚手架。在它的官网上,我看到了关键词SSR服务端渲染。前端经过多年的发展会倒退吗?当然不是,历史的发展总是螺旋式上升的,这里的SSR不同于传统的方式。准确的说,这个技术应该叫SSG静态站点生成或者Jamstack。
  NextJS 采用常规路由。pages目录下的文件名,如about.js,对应URL /about,默认导出的组件为页面组件。比较特别的是index.js对应的是/。除此之外,还有动态路由,它要求文件名用方括号括起来,例如 [tag].js。可以匹配/a、/someThing、/?tag=crumb等。 pages目录默认为页面级组件,共享组件放在src/component。
  框架提供了useRoute Hook,方便我们使用路由api。这里主要是希望在页面切换时监听切换事件,改变加载状态,改善弱网环境下的用户体验(其实很难看到这个切换过程,后面的原因又来了)。监听路由切换很方便,但是如果每个页面都需要注册一次监听,并且在组件卸载的时候取消监听,会出现太多重复的代码。
  NextJS 提供了修改容器组件的功能,在 pages 文件夹中新建一个 _app.js:
  // _app.tsx节选
function MyApp({ Component, pageProps }: AppProps) {
const [loading, setLoading] = useState(false)
const router = useRouter()
const startLoading = () => {
console.log(&#39;route change start&#39;)
setLoading(true)
}
const stopLoading = () => {
console.log(&#39;route change complete&#39;)
setLoading(false)
}
useEffect(() => {
router.events.on(&#39;routeChangeStart&#39;, startLoading)
router.events.on(&#39;routeChangeComplete&#39;, stopLoading)
router.events.on(&#39;routeChangeError&#39;, stopLoading)
return () => {
router.events.off(&#39;routeChangeStart&#39;, startLoading)
router.events.off(&#39;routeChangeComplete&#39;, stopLoading)
router.events.on(&#39;routeChangeError&#39;, stopLoading)
}
}, [])
return (





{`
body {
background-color: #f6f6f6
};
`}

)
}
  上面代码中使用了内置的css-in-component,一种内联样式的写法。我当时使用的 React 版本已经有了 Hooks。我在整个博客代码中使用了功能组件。其实这里也可以使用类组件。
  数据获取
  前面提到过,NextJS 允许搜索引擎获取预渲染的、带有数据的静态页面,那么如何在 Next 中获取数据呢?
  CI/CD、无服务器和 GraphQL
  一开始打算用Github Actions进行自动部署,但碰巧遇到了Next更新,而且Next所属的Vercel云服务比较好用,所以选择了官方推荐的方式,只要你提供一个链接到 git 仓库,Vercel 会在每次推送后自动以 serverless 的形式部署,并提供域名和 HTTPS 证书(其实就是 Let's Encypt 的证书)。
  此时,我想将后端转换为无服务器应用程序。顺便发现了hasura,它可以提供免费的GraphQL服务。只要有 postgresql 数据库,就可以生成基于 GraphQL 的后端。简单的CRUD完全没问题,所以没有继续折腾。但是对于前端,我只是想在构建过程中获取数据。Apollo 对我来说太重了,所以我找到了 graphql-request 库,它基本上只是对 fetch 的简单封装,足够使用 .
  // 示例
const response = await request(GraphQLEndpoint, query, variables)
  Link、Shallow Routing、Screening Paging 前面提到,服务器端渲染在切换页面的速度上存在缺陷,因为请求新页面需要返回新页面的完整静态文件,即使大部分页面布局没有改变了。Next 提供的 Link 组件,默认会在空闲时自动请求 JSON 数据,这样当用户点击链接时,可以快速改变内容,渲染新的页面。这也是因为我在非弱网络环境中看到了这一点。没有页面加载效果。
  在我的博客中,我为 文章 模型设置了很多外键,例如 文章 列、标签和分页。如果我想为这些设置页面,Next 提供了一种避免重新抓取的方法。浅路由,获取数据更新页面的方式:
  // 代码节选
route.push(`/posts?column=${item.column.name}`, undefined, { shallow: true })}>{item.column.name}
const route = useRoute()
useEffect(() => {
if (column) {
setArticles(articles => sourceArticles.filter(article => article.column.name === route.query.column))
}
console.log(articles)
}, [route.query.column])
  在useEffect的Hook中,根据route.query.column的变化判断是否更新文章数据源,过滤即可,无需重新取数据,并且页面仅部分更新。
  但是我很贪心,想用静态模式,每次只获取过滤需要的数据,而不是一次性获取所有数据,在客户端进行过滤,这个可以借助帮助动态路由的(这里我使用 TypeScript,Next 完全支持 TS):
  pages
├── about.tsx
├── _app.tsx
├── posts
│ └── [id].tsx
├── series.tsx
└── [column]
│ └── [page].tsx
├── [tag]
│ └── [page].tsx
└── [page].tsx
  但是这种形式,对栏目、标签、页面的过滤其实就是首页列表页,导致只有getStaticPaths函数不同,其余都是重复代码,不能接受,只有这样才可以接受 /[column]/[page 的路由,但不接受 /column=Python&amp;page=2 的查询形式。
  那么有没有办法一次接受所有的动态路由呢?其实有,一个叫[...slug]的页面组件就可以了,但是参数只能是数组,比如['a','b']对应/a/b,所以可以' t 区分Column和tag,并且如上所述,不能以查询参数的形式访问。
  在这方面,有一个问题。在某个版本中可以实现getStaticParams等API。对于博客等小数据的应用,使用 Shallow Routing 完全没问题,但对于 知乎 这样的大平台,过滤、搜索、分页都是必不可少的。
  下一步
  现在我博客原有的Django部分已经完全废弃了,自然不能使用Django提供的管理后台。Blazor在上一篇文章文章中介绍过,预计还要几个周末才能到。构建 SPA 后端。毕竟后端应用不需要SEO,SPA会更合适。CSharp 用于编写前端。过去,JS 渗透到桌面和移动端。反过来,静态语言开始蚕食 web 前端。
  总的来说,这个博客的不断重建过程,也是我学习一些前端技巧的一个实验过程。在这个过程中,我感觉自己经历了前端技术的发展变化。工程化、系统化,随着Node和一些框架的发展,前端开发体验也在不断提升。博客本身就变成了一个实验室,各种事情轮番经历。这个过程暂时不会停止。毕竟,业余时间写代码是很有趣的。博客已开源。

jquery抓取网页内容(使用HtmlAgilityPack一段时间.....推荐答案)

网站优化优采云 发表了文章 • 0 个评论 • 55 次浏览 • 2022-04-14 11:24 • 来自相关话题

  jquery抓取网页内容(使用HtmlAgilityPack一段时间.....推荐答案)
  问题描述
  我已经使用 HtmlAgilityPack 有一段时间了,但是我现在使用的 Web 资源有一个(看起来像)浏览器通过的 jQuery 协议。我希望加载的是产品页面,但实际加载的是(通过 WebBrowser 控件和 WebClient DownloadString Verification)是一个重定向,它要求访问者选择顾问并与他们注册。
  换句话说,使用 Chrome 的 Inspect &gt;&gt; Elements 工具,我得到:
  


  但是 WebBrowser 和 HTMLAgilityPack 只能得到:
  


&times;

It looks like you haven't selected a Consultant yet!
<p style="text-align: center;">...were you just wanting to browse or were you looking to shop and pick a Consultant to shop under?


...
</p>
  在深入研究标题的类定义后,我发现页面确实使用 jQuery 来处理正确的加载,并在访问者浏览页面时处理操作(滚动、调整大小、悬停在图像上、选择其他图像等)。这是来自 jQuery 的标头:
  /*!
* jQuery JavaScript Library v2.1.4
* http://jquery.com/
*
* Includes Sizzle.js
* http://sizzlejs.com/
*
* Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2015-04-28T16:01Z
*/
  我按照此处所述尝试了 ScrapySharp:C# .NET: Scraping Dynamics (JS) 网站
  但这最终会消耗所有可用内存并且什么也不会产生。
  这也是:htmlagilitypack 和动态内容问题加载错误重定向如上。
  如果需要,我可以提供更多我试图从中提取的源代码,包括完整的 jQuery。
  推荐答案
  使用 CaptureRedirect = false; 绕过重定向页面。对于您提到的页面,这对我有用:
  var web = new HtmlWeb();
web.CaptureRedirect = false;
web.BrowserTimeout = TimeSpan.FromSeconds(15);
  现在继续尝试,直到您在页面上看到文本“产品描述”。
  var doc = web.LoadFromBrowser(url, html =>
{
return html.Contains("Product Description");
});
  最新版本的 HtmlAgilityPack 可以在后台运行浏览器。所以我们真的不需要像 ScrapySharp 这样的库来抓取动态内容。 查看全部

  jquery抓取网页内容(使用HtmlAgilityPack一段时间.....推荐答案)
  问题描述
  我已经使用 HtmlAgilityPack 有一段时间了,但是我现在使用的 Web 资源有一个(看起来像)浏览器通过的 jQuery 协议。我希望加载的是产品页面,但实际加载的是(通过 WebBrowser 控件和 WebClient DownloadString Verification)是一个重定向,它要求访问者选择顾问并与他们注册。
  换句话说,使用 Chrome 的 Inspect &gt;&gt; Elements 工具,我得到:
  


  但是 WebBrowser 和 HTMLAgilityPack 只能得到:
  


&times;

It looks like you haven't selected a Consultant yet!
<p style="text-align: center;">...were you just wanting to browse or were you looking to shop and pick a Consultant to shop under?


...
</p>
  在深入研究标题的类定义后,我发现页面确实使用 jQuery 来处理正确的加载,并在访问者浏览页面时处理操作(滚动、调整大小、悬停在图像上、选择其他图像等)。这是来自 jQuery 的标头:
  /*!
* jQuery JavaScript Library v2.1.4
* http://jquery.com/
*
* Includes Sizzle.js
* http://sizzlejs.com/
*
* Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2015-04-28T16:01Z
*/
  我按照此处所述尝试了 ScrapySharp:C# .NET: Scraping Dynamics (JS) 网站
  但这最终会消耗所有可用内存并且什么也不会产生。
  这也是:htmlagilitypack 和动态内容问题加载错误重定向如上。
  如果需要,我可以提供更多我试图从中提取的源代码,包括完整的 jQuery。
  推荐答案
  使用 CaptureRedirect = false; 绕过重定向页面。对于您提到的页面,这对我有用:
  var web = new HtmlWeb();
web.CaptureRedirect = false;
web.BrowserTimeout = TimeSpan.FromSeconds(15);
  现在继续尝试,直到您在页面上看到文本“产品描述”。
  var doc = web.LoadFromBrowser(url, html =>
{
return html.Contains("Product Description");
});
  最新版本的 HtmlAgilityPack 可以在后台运行浏览器。所以我们真的不需要像 ScrapySharp 这样的库来抓取动态内容。

jquery抓取网页内容(服务器君一共花费了5.978ms进行了6次数据库查询)

网站优化优采云 发表了文章 • 0 个评论 • 118 次浏览 • 2022-04-14 02:22 • 来自相关话题

  jquery抓取网页内容(服务器君一共花费了5.978ms进行了6次数据库查询)
  服务器总共花费了 5.978 ms 进行了 6 次数据库查询,努力为您提供了这个页面。
  使用 JQuery 添加、获取和更改 HTML 元素的内容非常容易,而且您会对这种简单性感到非常满意。我们先来看看demo:
  效果演示
  欢迎来到简明现代魔法图书馆
  html() 方法
  此方法类似于 JavaScript 中的 innerHTML 属性,可用于读取或设置元素的 HTML 内容。要获取元素的内容,可以这样做:
  
var p_html = $("p").html(); //获取p元素的HTML代码
  如果需要设置元素的HTML代码,也可以使用该方法,但需要为其传递参数。例如设置p元素的HTML代码,可以使用如下代码:
  
//设置p元素的HTML代码
$("p").html("欢迎您访问简明现代魔法图书馆~~");
  注意:html() 方法可以用于 XHTML 文档,但不能用于 XML 文档。
  text() 方法
  此方法类似于 JavaScript 中的 innerText 属性,可用于读取或取消设置元素的文本内容。继续使用上面的HTML代码,使用text()方法对p元素进行操作:
  
var p_text = $("p").text(); //获取p元素的文本内容
  和html()方法一样,如果需要给一个元素设置文本内容,也需要传一个参数。比如设置p元素的文本内容,代码如下:
  
// 设置p元素的文本内容
$("p").text("欢迎您访问简明现代魔法图书馆~~");
  注意以下两点:
  JavaScript 中的 innerText 属性在 Firefox 浏览器中不起作用,而 jQuery 的 text() 方法支持所有浏览器。 text() 方法适用于 HTML 文档和 XML 文档。 查看全部

  jquery抓取网页内容(服务器君一共花费了5.978ms进行了6次数据库查询)
  服务器总共花费了 5.978 ms 进行了 6 次数据库查询,努力为您提供了这个页面。
  使用 JQuery 添加、获取和更改 HTML 元素的内容非常容易,而且您会对这种简单性感到非常满意。我们先来看看demo:
  效果演示
  欢迎来到简明现代魔法图书馆
  html() 方法
  此方法类似于 JavaScript 中的 innerHTML 属性,可用于读取或设置元素的 HTML 内容。要获取元素的内容,可以这样做:
  
var p_html = $("p").html(); //获取p元素的HTML代码
  如果需要设置元素的HTML代码,也可以使用该方法,但需要为其传递参数。例如设置p元素的HTML代码,可以使用如下代码:
  
//设置p元素的HTML代码
$("p").html("欢迎您访问简明现代魔法图书馆~~");
  注意:html() 方法可以用于 XHTML 文档,但不能用于 XML 文档。
  text() 方法
  此方法类似于 JavaScript 中的 innerText 属性,可用于读取或取消设置元素的文本内容。继续使用上面的HTML代码,使用text()方法对p元素进行操作:
  
var p_text = $("p").text(); //获取p元素的文本内容
  和html()方法一样,如果需要给一个元素设置文本内容,也需要传一个参数。比如设置p元素的文本内容,代码如下:
  
// 设置p元素的文本内容
$("p").text("欢迎您访问简明现代魔法图书馆~~");
  注意以下两点:
  JavaScript 中的 innerText 属性在 Firefox 浏览器中不起作用,而 jQuery 的 text() 方法支持所有浏览器。 text() 方法适用于 HTML 文档和 XML 文档。

jquery抓取网页内容(亿速云行业资讯频道频道详细介绍,介绍介绍)

网站优化优采云 发表了文章 • 0 个评论 • 49 次浏览 • 2022-04-12 00:21 • 来自相关话题

  jquery抓取网页内容(亿速云行业资讯频道频道详细介绍,介绍介绍)
  这篇文章主要介绍jquery获取html元素内容的方法。很详细,有一定的参考价值。有兴趣的朋友一定要读一读!
  jquery获取html元素内容的方法:1、使用html()返回被选中元素的内容,语法“$(selector).html()”;2、使用text()返回被选中元素的文本内容,语法“$(selector).text()”。
  1、html():返回原创HTML文档,但在IE中可能有兼容性,如下
  

Document
<p id="box">
<p class="b2">我是一个p元素
你好
</p>
$(function(){
var str = $("#box").html();
console.log(str);
//
  我是一个p元素
// 你好
//解释:该方法使用的是JS中的innerHTML()有些浏览器返回的结果可能不是原始文档的 HTML 源代码。例如,如果属性值只包含字母数字字符,Internet Explorer有时丢弃包裹属性值的引号
});
</p>
  2、text():获取匹配元素集中每个元素的组合文本,包括它们的后代
  

Document
<p id="box">
<p class="b2">我是一个p元素
你好
</p>
$(function(){ var str = $("#box").text();
console.log(str); // 我是一个p元素
// 你好 });
</p>
  3、val() 方法
  以上就是jquery获取html元素内容的方法的全部内容,感谢阅读!希望分享的内容对您有所帮助。更多相关知识,请关注易宿云行业资讯频道! 查看全部

  jquery抓取网页内容(亿速云行业资讯频道频道详细介绍,介绍介绍)
  这篇文章主要介绍jquery获取html元素内容的方法。很详细,有一定的参考价值。有兴趣的朋友一定要读一读!
  jquery获取html元素内容的方法:1、使用html()返回被选中元素的内容,语法“$(selector).html()”;2、使用text()返回被选中元素的文本内容,语法“$(selector).text()”。
  1、html():返回原创HTML文档,但在IE中可能有兼容性,如下
  

Document
<p id="box">
<p class="b2">我是一个p元素
你好
</p>
$(function(){
var str = $("#box").html();
console.log(str);
//
  我是一个p元素
// 你好
//解释:该方法使用的是JS中的innerHTML()有些浏览器返回的结果可能不是原始文档的 HTML 源代码。例如,如果属性值只包含字母数字字符,Internet Explorer有时丢弃包裹属性值的引号
});
</p>
  2、text():获取匹配元素集中每个元素的组合文本,包括它们的后代
  

Document
<p id="box">
<p class="b2">我是一个p元素
你好
</p>
$(function(){ var str = $("#box").text();
console.log(str); // 我是一个p元素
// 你好 });
</p>
  3、val() 方法
  以上就是jquery获取html元素内容的方法的全部内容,感谢阅读!希望分享的内容对您有所帮助。更多相关知识,请关注易宿云行业资讯频道!

jquery抓取网页内容(jquery抓取网页内容方法很多,关键是要选好代理)

网站优化优采云 发表了文章 • 0 个评论 • 62 次浏览 • 2022-04-11 17:02 • 来自相关话题

  jquery抓取网页内容(jquery抓取网页内容方法很多,关键是要选好代理)
  jquery抓取网页内容方法很多,关键是要选好代理,
  jquery可以抓取网页任何部分,比如图片,比如源代码,比如json等等。手动要解析得在一两个小时,难度太大。除非你有专门的程序员,买点机器。
  浏览器上装一个插件img1pass。js进阶可以装个qq浏览器插件mlook,因为在html版本较低的时候。效果比较好的。
  javascript(和css)能力达到一定水平即可
  首先需要把数据抓取来,然后用javascript去操作加载javascript时的页面,最后可以通过json格式的网页数据拼接来提取你需要的关键字,完成真正抓取。
  之前专门研究过这个问题。抓取js就可以了。谷歌曾经有个实验,模拟浏览器进程去抓取非html,这样抓取每页的请求数会比javascript下方法多得多,效率也提高了。谷歌,百度都这么搞的,提供cookie。你也可以关注本专栏,关注不同的爬虫方法。
  不会。建议回头看看自己老板是怎么做的。
  jquery本身只是提供一个api,客户端提供的js文件可以自己处理,jquery加javascript才能执行,爬虫本身一般只提供javascriptapi,如果有需要javascript文件来传递数据,可以使用python的jquery库。
  jquery最近网上方法基本上都不适用了,缺点网页抓取本身的姿势要求还是很多,如果是想研究ui方面的,建议看requests这个库, 查看全部

  jquery抓取网页内容(jquery抓取网页内容方法很多,关键是要选好代理)
  jquery抓取网页内容方法很多,关键是要选好代理,
  jquery可以抓取网页任何部分,比如图片,比如源代码,比如json等等。手动要解析得在一两个小时,难度太大。除非你有专门的程序员,买点机器。
  浏览器上装一个插件img1pass。js进阶可以装个qq浏览器插件mlook,因为在html版本较低的时候。效果比较好的。
  javascript(和css)能力达到一定水平即可
  首先需要把数据抓取来,然后用javascript去操作加载javascript时的页面,最后可以通过json格式的网页数据拼接来提取你需要的关键字,完成真正抓取。
  之前专门研究过这个问题。抓取js就可以了。谷歌曾经有个实验,模拟浏览器进程去抓取非html,这样抓取每页的请求数会比javascript下方法多得多,效率也提高了。谷歌,百度都这么搞的,提供cookie。你也可以关注本专栏,关注不同的爬虫方法。
  不会。建议回头看看自己老板是怎么做的。
  jquery本身只是提供一个api,客户端提供的js文件可以自己处理,jquery加javascript才能执行,爬虫本身一般只提供javascriptapi,如果有需要javascript文件来传递数据,可以使用python的jquery库。
  jquery最近网上方法基本上都不适用了,缺点网页抓取本身的姿势要求还是很多,如果是想研究ui方面的,建议看requests这个库,

jquery抓取网页内容(Xpath:简单易用的网页内容提取工具学习爽,一直学习一直爽!)

网站优化优采云 发表了文章 • 0 个评论 • 63 次浏览 • 2022-04-10 23:37 • 来自相关话题

  jquery抓取网页内容(Xpath:简单易用的网页内容提取工具学习爽,一直学习一直爽!)
  Xpath:一个易于使用的网页内容提取工具
  学习一时爽,学习永远爽!
  大家好,我是康纳,一个从零开始的技术新手。上次我们讲了如何使用请求。在上一课中,我们已经学习了所有常见的 Python 访问库。那么当我们得到我们访问的内容时,我们应该从网页中提取出我们想要的内容。因此,今天我们就来聊一聊常用的网页内容提取工具之一:Xpath。与 BeautifulSoup 相比,Xpath 更易于使用。
  1.Xpath 简介
  Xpath 是一种用于在 XML 文档中查找信息的语言。XPath 用于浏览 XML 文档中的元素和属性。他是一种路径语言(XML Path Language),用来确定一个XML文档的某一部分的位置。
  XPath 基于 XML 的树结构,它提供了在数据结构树中查找节点的能力。XPath 的初衷是将其用作 XPointer 和 XSL 之间的通用语法模型。但是 XPath 很快被开发人员采用,并被广泛用作小型*查询语言。例如,当您打开网页并按 F12 进行元素检查时。当要复制元素的路径时,可以通过右键进行复制操作。您将在里面找到 Copy Xpath 的选项。这显示了 Xpath 的广泛使用。
  说了这么多Xpath的使用范围有多大,使用起来有多么简单,让我们开始做正事,看看Xpath是如何在Python爬虫中用来爬取我们想要的内容的:
  2. Xpath 安装
  在之前的教程中,我几乎没有提到某个库的安装,但为什么我在这里提到如何安装呢?原因很简单,Xpath 只是 lxml 库中的一个模块。许多 Python 库都提供了 Xpath 函数,但最基本的是 lxml 库。最有效率。所以,你知道,要使用 Xpath,你需要安装 lxml 库:
  pip install lxml
复制代码
  3.Xpath 语法
  其实说白了,Xpath就是从html中选择节点。通过以下路径或步骤选择节点。下面,我们将通过以下HTML文档进行演示:
  html_doc ="""








总裁的新鲜小妻子







斗神天下


"""
复制代码
  首先大家都知道,我们实际上从网页中得到的是字符串格式。所以如果我们想通过 Xpath 提取我们想要的东西,我们首先需要生成 HTML DOM 树:
  from lxml import etree
page = etree.HTML(html_doc)
复制代码
  3.1 路径查找
  如果我们要使用寻路,我们首先需要知道 Xpath 的语法。Xpath的主要语法如下:
  表达式描述
  节点名
  选择名为nodename的子节点
  /
  从根节点挑选
  //
  从与选择匹配的当前节点中选择文档中的节点,而不考虑它们的位置。
  .
  选择当前节点
  ..
  选择当前节点的父节点
  @
  选择属性
  In [1]: page.xpath(&#39;head&#39;)
Out[1]: []
复制代码
  当前节点位置在html中,所以可以直接查询头节点,li是html的孙子节点,如果查询li则返回空值:
  In [2]: page.xpath(&#39;li&#39;)
Out[2]: []
复制代码
  In [3]: page.xpath(&#39;/html&#39;)
Out[3]: []
复制代码
  从根节点搜索,根节点下只有一个节点html节点,所以从根节点只能找到html,如果搜索其他内容,会返回一个空列表:
  In [4]: page.xpath(&#39;/li&#39;)
Out[4]: []
复制代码
  In [5]: page.xpath(&#39;//li&#39;)
Out[5]:
[,
,
,
]
复制代码
  从整个文档中查找在整个文档中查找符合条件的节点,包括孙节点及以下。
  In [6]: page.xpath(&#39;//li&#39;)[0].xpath(&#39;..&#39;)
Out[6]: []
复制代码
  In [7]: page.xpath(&#39;//a&#39;)[1].xpath(&#39;@href&#39;)
Out[7]: [&#39;/book_16860.html&#39;]
复制代码
  选中属性支持任意标签属性,但需要注意的是,如果选中的节点有多个,需要指定是哪个节点的属性。
  3.2 节点查找
  通过路径找到节点后,我们需要从超级找到的节点中选择我们需要的内容。还有一些查找节点的语法,如下:
  表达结果
  节点名[索引]
  选择满足要求的第 index 个元素
  节点名[last()]
  选择最后一个元素
  节点名[位置()
  选择前 num 个元素
  节点名[@attribute]
  选择属性名为attribute的元素
  节点名[@attribute='值']
  选择具有属性名称属性和值值的元素
  In [1]: page.xpath(&#39;//li[1]/a[1]/img[1]/@src&#39;)
Out[1]: [&#39;/16860s.jpg&#39;]
复制代码
  **注意:选择节点的属性时需要注意一件事。[index] 选择的节点是每个条件的第 [index] 个合格元素。**不过这个比较抽象,举个例子吧。例如:
  In [2]: page.xpath(&#39;//li[1]&#39;) 选取所有符合 li 节点的第一个节点
Out[2]: []
复制代码
  从上面的例子中,我们似乎什么都看不到,那么我们来看下面的例子:
  In [3]: page.xpath(&#39;//li//img[1]&#39;)
Out[3]: [,
,
,
]
复制代码
  如您所见,我们选择了 4 个 img 节点。原因很简单,看下面的代码和解释就明白了:
  




(一)

(二)
(三)
总裁的新鲜小妻子



(四)

(五)
(六)
斗神天下


复制代码
  (一) 是第一个节点中的第一个节点
  节点。它的路径是 //
  (二) 是第一个节点的
  首先在节点
  节点。它的路径是/
  . (三) 没有被选中,因为它是标签下的第二个
  标签 (四) (五) (六)类似
  In [4]: page.xpath(&#39;//img[position()>1]&#39;)
Out[4]: [, ]
复制代码
  3.3 匹配未知节点
  当我们匹配时,会有一条不确定的路径。此时,我们将涉及匹配未知节点。匹配未知节点也有对应的语法,如下:
  通配符说明
  *
  匹配任何元素节点
  @*
  匹配任何属性节点
  匹配任意属性节点:
  In [1]: page.xpath(&#39;//li/a/*&#39;)
Out[1]: [,
,
,
]
复制代码
  匹配任何元素节点:
  In [2]: page.xpath(&#39;//li/a[@*]&#39;)
Out[2]: [,
,
,
]
复制代码
  3.4 获取节点中的文本
  可以通过attribute方法获取属性中的内容,但无法获取节点之间的内容。这时可以通过 text() 和 string() 方法获取其中的文本:
  使用 text() 获取节点中的文本:
  In [1]: page.xpath(&#39;//li/a[3]/text()&#39;)
Out[1]: [&#39;总裁的新鲜小妻子&#39;, &#39;斗神天下&#39;]
复制代码
  如您所见,标签之间的文本可以通过 text() 属性轻松获取。
  使用 string() 获取节点中的文本:
  In [1]: page.xpath(&#39;string(//li[1]/a[3])&#39;)
Out[1]: &#39;总裁的新鲜小妻子&#39;
复制代码
  3.5 选择多个路径
  有时我们需要同时查找多个条件。此时,您可以通过在路径表达式中使用竖线字符(“|”)来选择多个路径:
  In [1]: page.xpath(&#39;//li[1]/img[2]/@src | //li[1]/a[3]/text()&#39;)
Out[1]: [&#39;/kukuku/images/second.png&#39;, &#39;总裁的新鲜小妻子&#39;]
复制代码
  同时选择多条路径不会生成新的列表,只会生成一个列表,所以你需要考虑如何提取你返回的结果。一般来说,不建议使用多个条件进行搜索,因为将多个提取结果混合在一个列表中不利于提取。即使可以提取,也会增加计算量,降低程序性能。所以,尽量不要使用这种方法。
  下一条通知:
  Xpath用起来还是那么费劲,有没有其他更简单的方法?? ? 当然有,你可以用美味的汤完成你需要做的事情。敬请关注下一期 - BeautifulSoup:美味汤
  以上就是所有Xpath相关的内容了,可能没有其他的详细,但是对于你作为爬虫使用来说已经足够了。其实我也希望能详细一点,不过我是常客,个人不太喜欢用Xpath。如果你真的想深入了解 Xpth,我建议你去 W3C Xpath 教程 &gt;&gt;&gt; 看看他们是如何使用它的。
  好了,今天就到这里,我是康纳,一个从零开始的技术菜鸟。不知道你今天收获了多少?? ? 下次见!
  学习一时爽,学习永远爽!
  系列文章连接:
  Python爬虫十六种形式——第一种形式:HTTP协议&gt;&gt;&gt;
  Python爬虫十六式二:urllib和urllib3 &gt;&gt;&gt;
  Python爬虫十六式-第三式:Requests的用法&gt;&gt;&gt;
  Python爬虫十六-五:BeautifulSoup,美味的汤&gt;&gt;&gt;
  Python爬虫十六式六:JQuery的假兄弟-pyquery &gt;&gt;&gt;
  Python爬虫十六式七:正则美术&gt;&gt;&gt;
  Python爬虫十六式——第八式:实例分析——全书网&gt;&gt;&gt;
  转载于: 查看全部

  jquery抓取网页内容(Xpath:简单易用的网页内容提取工具学习爽,一直学习一直爽!)
  Xpath:一个易于使用的网页内容提取工具
  学习一时爽,学习永远爽!
  大家好,我是康纳,一个从零开始的技术新手。上次我们讲了如何使用请求。在上一课中,我们已经学习了所有常见的 Python 访问库。那么当我们得到我们访问的内容时,我们应该从网页中提取出我们想要的内容。因此,今天我们就来聊一聊常用的网页内容提取工具之一:Xpath。与 BeautifulSoup 相比,Xpath 更易于使用。
  1.Xpath 简介
  Xpath 是一种用于在 XML 文档中查找信息的语言。XPath 用于浏览 XML 文档中的元素和属性。他是一种路径语言(XML Path Language),用来确定一个XML文档的某一部分的位置。
  XPath 基于 XML 的树结构,它提供了在数据结构树中查找节点的能力。XPath 的初衷是将其用作 XPointer 和 XSL 之间的通用语法模型。但是 XPath 很快被开发人员采用,并被广泛用作小型*查询语言。例如,当您打开网页并按 F12 进行元素检查时。当要复制元素的路径时,可以通过右键进行复制操作。您将在里面找到 Copy Xpath 的选项。这显示了 Xpath 的广泛使用。
  说了这么多Xpath的使用范围有多大,使用起来有多么简单,让我们开始做正事,看看Xpath是如何在Python爬虫中用来爬取我们想要的内容的:
  2. Xpath 安装
  在之前的教程中,我几乎没有提到某个库的安装,但为什么我在这里提到如何安装呢?原因很简单,Xpath 只是 lxml 库中的一个模块。许多 Python 库都提供了 Xpath 函数,但最基本的是 lxml 库。最有效率。所以,你知道,要使用 Xpath,你需要安装 lxml 库:
  pip install lxml
复制代码
  3.Xpath 语法
  其实说白了,Xpath就是从html中选择节点。通过以下路径或步骤选择节点。下面,我们将通过以下HTML文档进行演示:
  html_doc ="""








总裁的新鲜小妻子







斗神天下


"""
复制代码
  首先大家都知道,我们实际上从网页中得到的是字符串格式。所以如果我们想通过 Xpath 提取我们想要的东西,我们首先需要生成 HTML DOM 树:
  from lxml import etree
page = etree.HTML(html_doc)
复制代码
  3.1 路径查找
  如果我们要使用寻路,我们首先需要知道 Xpath 的语法。Xpath的主要语法如下:
  表达式描述
  节点名
  选择名为nodename的子节点
  /
  从根节点挑选
  //
  从与选择匹配的当前节点中选择文档中的节点,而不考虑它们的位置。
  .
  选择当前节点
  ..
  选择当前节点的父节点
  @
  选择属性
  In [1]: page.xpath(&#39;head&#39;)
Out[1]: []
复制代码
  当前节点位置在html中,所以可以直接查询头节点,li是html的孙子节点,如果查询li则返回空值:
  In [2]: page.xpath(&#39;li&#39;)
Out[2]: []
复制代码
  In [3]: page.xpath(&#39;/html&#39;)
Out[3]: []
复制代码
  从根节点搜索,根节点下只有一个节点html节点,所以从根节点只能找到html,如果搜索其他内容,会返回一个空列表:
  In [4]: page.xpath(&#39;/li&#39;)
Out[4]: []
复制代码
  In [5]: page.xpath(&#39;//li&#39;)
Out[5]:
[,
,
,
]
复制代码
  从整个文档中查找在整个文档中查找符合条件的节点,包括孙节点及以下。
  In [6]: page.xpath(&#39;//li&#39;)[0].xpath(&#39;..&#39;)
Out[6]: []
复制代码
  In [7]: page.xpath(&#39;//a&#39;)[1].xpath(&#39;@href&#39;)
Out[7]: [&#39;/book_16860.html&#39;]
复制代码
  选中属性支持任意标签属性,但需要注意的是,如果选中的节点有多个,需要指定是哪个节点的属性。
  3.2 节点查找
  通过路径找到节点后,我们需要从超级找到的节点中选择我们需要的内容。还有一些查找节点的语法,如下:
  表达结果
  节点名[索引]
  选择满足要求的第 index 个元素
  节点名[last()]
  选择最后一个元素
  节点名[位置()
  选择前 num 个元素
  节点名[@attribute]
  选择属性名为attribute的元素
  节点名[@attribute='值']
  选择具有属性名称属性和值值的元素
  In [1]: page.xpath(&#39;//li[1]/a[1]/img[1]/@src&#39;)
Out[1]: [&#39;/16860s.jpg&#39;]
复制代码
  **注意:选择节点的属性时需要注意一件事。[index] 选择的节点是每个条件的第 [index] 个合格元素。**不过这个比较抽象,举个例子吧。例如:
  In [2]: page.xpath(&#39;//li[1]&#39;) 选取所有符合 li 节点的第一个节点
Out[2]: []
复制代码
  从上面的例子中,我们似乎什么都看不到,那么我们来看下面的例子:
  In [3]: page.xpath(&#39;//li//img[1]&#39;)
Out[3]: [,
,
,
]
复制代码
  如您所见,我们选择了 4 个 img 节点。原因很简单,看下面的代码和解释就明白了:
  




(一)

(二)
(三)
总裁的新鲜小妻子



(四)

(五)
(六)
斗神天下


复制代码
  (一) 是第一个节点中的第一个节点
  节点。它的路径是 //
  (二) 是第一个节点的
  首先在节点
  节点。它的路径是/
  . (三) 没有被选中,因为它是标签下的第二个
  标签 (四) (五) (六)类似
  In [4]: page.xpath(&#39;//img[position()>1]&#39;)
Out[4]: [, ]
复制代码
  3.3 匹配未知节点
  当我们匹配时,会有一条不确定的路径。此时,我们将涉及匹配未知节点。匹配未知节点也有对应的语法,如下:
  通配符说明
  *
  匹配任何元素节点
  @*
  匹配任何属性节点
  匹配任意属性节点:
  In [1]: page.xpath(&#39;//li/a/*&#39;)
Out[1]: [,
,
,
]
复制代码
  匹配任何元素节点:
  In [2]: page.xpath(&#39;//li/a[@*]&#39;)
Out[2]: [,
,
,
]
复制代码
  3.4 获取节点中的文本
  可以通过attribute方法获取属性中的内容,但无法获取节点之间的内容。这时可以通过 text() 和 string() 方法获取其中的文本:
  使用 text() 获取节点中的文本:
  In [1]: page.xpath(&#39;//li/a[3]/text()&#39;)
Out[1]: [&#39;总裁的新鲜小妻子&#39;, &#39;斗神天下&#39;]
复制代码
  如您所见,标签之间的文本可以通过 text() 属性轻松获取。
  使用 string() 获取节点中的文本:
  In [1]: page.xpath(&#39;string(//li[1]/a[3])&#39;)
Out[1]: &#39;总裁的新鲜小妻子&#39;
复制代码
  3.5 选择多个路径
  有时我们需要同时查找多个条件。此时,您可以通过在路径表达式中使用竖线字符(“|”)来选择多个路径:
  In [1]: page.xpath(&#39;//li[1]/img[2]/@src | //li[1]/a[3]/text()&#39;)
Out[1]: [&#39;/kukuku/images/second.png&#39;, &#39;总裁的新鲜小妻子&#39;]
复制代码
  同时选择多条路径不会生成新的列表,只会生成一个列表,所以你需要考虑如何提取你返回的结果。一般来说,不建议使用多个条件进行搜索,因为将多个提取结果混合在一个列表中不利于提取。即使可以提取,也会增加计算量,降低程序性能。所以,尽量不要使用这种方法。
  下一条通知:
  Xpath用起来还是那么费劲,有没有其他更简单的方法?? ? 当然有,你可以用美味的汤完成你需要做的事情。敬请关注下一期 - BeautifulSoup:美味汤
  以上就是所有Xpath相关的内容了,可能没有其他的详细,但是对于你作为爬虫使用来说已经足够了。其实我也希望能详细一点,不过我是常客,个人不太喜欢用Xpath。如果你真的想深入了解 Xpth,我建议你去 W3C Xpath 教程 &gt;&gt;&gt; 看看他们是如何使用它的。
  好了,今天就到这里,我是康纳,一个从零开始的技术菜鸟。不知道你今天收获了多少?? ? 下次见!
  学习一时爽,学习永远爽!
  系列文章连接:
  Python爬虫十六种形式——第一种形式:HTTP协议&gt;&gt;&gt;
  Python爬虫十六式二:urllib和urllib3 &gt;&gt;&gt;
  Python爬虫十六式-第三式:Requests的用法&gt;&gt;&gt;
  Python爬虫十六-五:BeautifulSoup,美味的汤&gt;&gt;&gt;
  Python爬虫十六式六:JQuery的假兄弟-pyquery &gt;&gt;&gt;
  Python爬虫十六式七:正则美术&gt;&gt;&gt;
  Python爬虫十六式——第八式:实例分析——全书网&gt;&gt;&gt;
  转载于:

jquery抓取网页内容(从网页中准确提取所需的内容,你知道吗?)

网站优化优采云 发表了文章 • 0 个评论 • 56 次浏览 • 2022-04-07 13:01 • 来自相关话题

  jquery抓取网页内容(从网页中准确提取所需的内容,你知道吗?)
  1. 前言
  相信很多人在做开发的时候都有过这样的需求:准确的从网页中提取出需要的内容。想来想去,方法无外乎如下:(本人还是新手,有更好的方法,请指点)
  1. 使用正则表达式来匹配所需的元素。(缺点:如果同一类型的元素具有不同的属性,例如
  啊啊啊
  bbb
  , 如果要匹配所有的 div 元素,会比较麻烦,而且很容易得到不想要的结果而错过需要的结果。)
  2. 使用 Linq to XML 将网页转换为 XML 文档。(缺点:需要一个转换过程,效率不高。)
  3. 使用网站提供的WebServices或WebAPI等接口直接获取需要的数据。(缺点:需要先获取接口文档,一般不匿名提供。)
  随着近几年前端的兴起,越来越多的人开始认可和信服JQuery这个强大的工具。其中最重要的一点是JQuery选择器,简洁、高效、易学,大大提高了前端工程师的工作效率。. 想想看,提取网页内容就是在处理前端。如果可以使用 JQuery 选择器,那就完美了!!!
  2. 理论准备
  您想在.NET 下自己制作选择器吗?不,这不是我可以等待年轻一代去做的事情。. . . 既然 JQuery 已经存在,为什么不直接使用它的选择器呢?
  1. .NET 获取网页内容
  在这里您可以选择 webbrowser 控件。事实上,它是一个微型 IE,它可以做 IE 能做的所有事情。有人会问为什么不用WebClient直接下载网页内容呢?请看第二点。
  2. .NET 与 JS 交互
  使用webbrowser控件,不仅可以获得网页的内容,更重要的是提供了与网页交互的功能。使用内置的 Document 属性,我们可以将所需的 JS 代码注入网页并执行。
  3. 提取并返回所需内容
  在 .NET 中,我们可以使用 Docment 的 InvokeScript 函数来执行相应的 JS 函数并获取返回结果。
  现在理论已经准备好了,接下来让我们实现它。
  3. 函数实现
  测试页:(福利网站哦,不过绝对没有邪恶内容,请编辑明鉴!)
  功能要求:提取所有“好处”!!!!
  从图中可以看出,“福利”是准确提取出来的。而且您只能获得所需的属性值。您所要做的就是输入最短 15 个字符。
  我们看一下代码实现:
  其中wb为webbrowser控件,本节主要是将JQuery库注入到一些不收录JQuery库的网页中。
  无效的 InjectJQuery()
  {
  HtmlElement jquery = wb.Document.CreateElement("script");
  jquery.SetAttribute("src", "");
  wb.Document.Body.AppendChild(jquery);
  JQueryInjected = true;
  }
  这里是需要注入的JS函数。因为不同的需求有不同的代码,所以不能重复注入。当需求发生变化时,只需要更改注入的函数即可。
  JQScript = wb.Document.GetElementById("JQScript");
  如果(JQScript == null)
  {
  JQScript = wb.Document.CreateElement("script");
  JQScript.SetAttribute("id", "JQScript");
  JQScript.SetAttribute("type", "text/javascript");
  wb.Document.Body.AppendChild(JQScript);
  }
  这是关键代码,根据是否要提取属性生成不同的代码。注入的代码很简单,相信稍微懂一点前端的朋友一看就懂。而最后一行代码是执行注入的函数并获取返回值。
  if (txtAttribute.Text.Trim() == string.Empty)
  JQScript.SetAttribute("text", "function GetJQValue() { if ($('" + txtSelector.Text + "').length == 1) {" +
  "return $('" + txtSelector.Text + "')[0].outerHTML; }" +
  " else if ($('" + txtSelector.Text + "').length &gt; 1) {" +
  “var allhtml = '';” +
  " $('" + txtSelector.Text + "').each(function() {allhtml=allhtml+$(this)[0].outerHTML+'\\r\\n';});" +
  "返回所有html;}" +
  " else return '未找到项目。';}");
  别的
  {
  JQScript.SetAttribute("text", "function GetJQValue() { if ($('" + txtSelector.Text + "').length == 1) {" +
  "return $('" + txtSelector.Text + "').attr('" + txtAttribute.Text + "'); }" +
  " else if ($('" + txtSelector.Text + "').length &gt; 1) {" +
  “var allhtml = '';” +
  " $('" + txtSelector.Text + "').each(function() {allhtml=allhtml+$(this).attr('" + txtAttribute.Text + "')+'\\r\\n'; });" +
  "返回所有html;}" +
  " else return '未找到项目。';}");
  }
  textBox2.Text = wb.Document.InvokeScript("GetJQValue").ToString();
  相信大家一眼就看出来了。只需 10 行代码,您就可以使用强大的 JQuery 选择器。效率比旧方法高出许多倍。为什么不这样做? 查看全部

  jquery抓取网页内容(从网页中准确提取所需的内容,你知道吗?)
  1. 前言
  相信很多人在做开发的时候都有过这样的需求:准确的从网页中提取出需要的内容。想来想去,方法无外乎如下:(本人还是新手,有更好的方法,请指点)
  1. 使用正则表达式来匹配所需的元素。(缺点:如果同一类型的元素具有不同的属性,例如
  啊啊啊
  bbb
  , 如果要匹配所有的 div 元素,会比较麻烦,而且很容易得到不想要的结果而错过需要的结果。)
  2. 使用 Linq to XML 将网页转换为 XML 文档。(缺点:需要一个转换过程,效率不高。)
  3. 使用网站提供的WebServices或WebAPI等接口直接获取需要的数据。(缺点:需要先获取接口文档,一般不匿名提供。)
  随着近几年前端的兴起,越来越多的人开始认可和信服JQuery这个强大的工具。其中最重要的一点是JQuery选择器,简洁、高效、易学,大大提高了前端工程师的工作效率。. 想想看,提取网页内容就是在处理前端。如果可以使用 JQuery 选择器,那就完美了!!!
  2. 理论准备
  您想在.NET 下自己制作选择器吗?不,这不是我可以等待年轻一代去做的事情。. . . 既然 JQuery 已经存在,为什么不直接使用它的选择器呢?
  1. .NET 获取网页内容
  在这里您可以选择 webbrowser 控件。事实上,它是一个微型 IE,它可以做 IE 能做的所有事情。有人会问为什么不用WebClient直接下载网页内容呢?请看第二点。
  2. .NET 与 JS 交互
  使用webbrowser控件,不仅可以获得网页的内容,更重要的是提供了与网页交互的功能。使用内置的 Document 属性,我们可以将所需的 JS 代码注入网页并执行。
  3. 提取并返回所需内容
  在 .NET 中,我们可以使用 Docment 的 InvokeScript 函数来执行相应的 JS 函数并获取返回结果。
  现在理论已经准备好了,接下来让我们实现它。
  3. 函数实现
  测试页:(福利网站哦,不过绝对没有邪恶内容,请编辑明鉴!)
  功能要求:提取所有“好处”!!!!
  从图中可以看出,“福利”是准确提取出来的。而且您只能获得所需的属性值。您所要做的就是输入最短 15 个字符。
  我们看一下代码实现:
  其中wb为webbrowser控件,本节主要是将JQuery库注入到一些不收录JQuery库的网页中。
  无效的 InjectJQuery()
  {
  HtmlElement jquery = wb.Document.CreateElement("script");
  jquery.SetAttribute("src", "");
  wb.Document.Body.AppendChild(jquery);
  JQueryInjected = true;
  }
  这里是需要注入的JS函数。因为不同的需求有不同的代码,所以不能重复注入。当需求发生变化时,只需要更改注入的函数即可。
  JQScript = wb.Document.GetElementById("JQScript");
  如果(JQScript == null)
  {
  JQScript = wb.Document.CreateElement("script");
  JQScript.SetAttribute("id", "JQScript");
  JQScript.SetAttribute("type", "text/javascript");
  wb.Document.Body.AppendChild(JQScript);
  }
  这是关键代码,根据是否要提取属性生成不同的代码。注入的代码很简单,相信稍微懂一点前端的朋友一看就懂。而最后一行代码是执行注入的函数并获取返回值。
  if (txtAttribute.Text.Trim() == string.Empty)
  JQScript.SetAttribute("text", "function GetJQValue() { if ($('" + txtSelector.Text + "').length == 1) {" +
  "return $('" + txtSelector.Text + "')[0].outerHTML; }" +
  " else if ($('" + txtSelector.Text + "').length &gt; 1) {" +
  “var allhtml = '';” +
  " $('" + txtSelector.Text + "').each(function() {allhtml=allhtml+$(this)[0].outerHTML+'\\r\\n';});" +
  "返回所有html;}" +
  " else return '未找到项目。';}");
  别的
  {
  JQScript.SetAttribute("text", "function GetJQValue() { if ($('" + txtSelector.Text + "').length == 1) {" +
  "return $('" + txtSelector.Text + "').attr('" + txtAttribute.Text + "'); }" +
  " else if ($('" + txtSelector.Text + "').length &gt; 1) {" +
  “var allhtml = '';” +
  " $('" + txtSelector.Text + "').each(function() {allhtml=allhtml+$(this).attr('" + txtAttribute.Text + "')+'\\r\\n'; });" +
  "返回所有html;}" +
  " else return '未找到项目。';}");
  }
  textBox2.Text = wb.Document.InvokeScript("GetJQValue").ToString();
  相信大家一眼就看出来了。只需 10 行代码,您就可以使用强大的 JQuery 选择器。效率比旧方法高出许多倍。为什么不这样做?

jquery抓取网页内容(编写爬虫程序变的可能,实习操作起来非常的简单)

网站优化优采云 发表了文章 • 0 个评论 • 166 次浏览 • 2022-04-06 12:14 • 来自相关话题

  jquery抓取网页内容(编写爬虫程序变的可能,实习操作起来非常的简单)
  编写爬虫程序大多是后端开发者的工作,但是node的出现使得前端开发者编写爬虫程序成为可能,而且做法非常简单。
  我们首先介绍 SuperAgent,这是一个小型渐进式客户端 HTTP 请求库,其 API 与 Node.js 模块相同,具有许多高级 HTTP 客户端功能。从这个官方的解释可以看出,SuperAgent是一个实现http请求的库,封装在node环境中,实现对网页内容的请求。
  Cheerio 是在node 环境下,可以使用jquery api 之类的方法来获取网页的dom 中的数据。
  这两个工具结合起来抓取特定于业务的内容。我们都知道,在前端网页的开发中,经常会为样式相同的dom节点打上相同的类名,这样它们就可以具有相同的样式,这样就可以为我们在网页中抓取特定内容提供方便了。网页 。
  我们以某网站的消息为例:
  
  上图是新闻列表对应的代码。我们可以看到列表被包装在一个 id="xy-impcon" 的 div 容器中。每个分类的新闻列表使用ul,ul有一个通用的类名list-a。下面 ul 都有 li 标签和 a 标签。如果我们要获取每条新闻,可以使用cheerio来获取dom,可以写成$('#xy-impcon ul.list-a li a'),那么就写爬取链接和标题的程序,并将抓取数据保存到文件。
  var http = require("http"),
url = require("url"),
superagent = require("superagent"),
cheerio = require("cheerio"),
async = require("async"),
eventproxy = require('eventproxy');
var path = require('path');
var $ = require('jQuery');
var fs = require("fs");
var writerStream2 = fs.createWriteStream(path.resolve(__dirname,'../data/news.txt'),{ flags: 'w',encoding: null,mode: 0666 });
var text = [];
(function (){
superagent.get('爬取网站的url')
.end(function(err,pres){
var $ = cheerio.load(pres.text);
var curPageUrls = $('#xy-impcon ul.list-a li a');
console.log(curPageUrls.length)
curPageUrls.each(function(index, elem){
text.push({
title: $(elem).text(),
url: $(elem).attr('href')
})
})
writerStream2.write(JSON.stringify(text),'UTF8');
});
})();
  上面的代码将爬取的内容保存为文件。
  另外,我们还可以在node环境中使用phantomjs的网页模块,模拟浏览器端抓取网页数据,生成网页截图。具体用法后面会介绍 查看全部

  jquery抓取网页内容(编写爬虫程序变的可能,实习操作起来非常的简单)
  编写爬虫程序大多是后端开发者的工作,但是node的出现使得前端开发者编写爬虫程序成为可能,而且做法非常简单。
  我们首先介绍 SuperAgent,这是一个小型渐进式客户端 HTTP 请求库,其 API 与 Node.js 模块相同,具有许多高级 HTTP 客户端功能。从这个官方的解释可以看出,SuperAgent是一个实现http请求的库,封装在node环境中,实现对网页内容的请求。
  Cheerio 是在node 环境下,可以使用jquery api 之类的方法来获取网页的dom 中的数据。
  这两个工具结合起来抓取特定于业务的内容。我们都知道,在前端网页的开发中,经常会为样式相同的dom节点打上相同的类名,这样它们就可以具有相同的样式,这样就可以为我们在网页中抓取特定内容提供方便了。网页 。
  我们以某网站的消息为例:
  
  上图是新闻列表对应的代码。我们可以看到列表被包装在一个 id="xy-impcon" 的 div 容器中。每个分类的新闻列表使用ul,ul有一个通用的类名list-a。下面 ul 都有 li 标签和 a 标签。如果我们要获取每条新闻,可以使用cheerio来获取dom,可以写成$('#xy-impcon ul.list-a li a'),那么就写爬取链接和标题的程序,并将抓取数据保存到文件。
  var http = require("http"),
url = require("url"),
superagent = require("superagent"),
cheerio = require("cheerio"),
async = require("async"),
eventproxy = require('eventproxy');
var path = require('path');
var $ = require('jQuery');
var fs = require("fs");
var writerStream2 = fs.createWriteStream(path.resolve(__dirname,'../data/news.txt'),{ flags: 'w',encoding: null,mode: 0666 });
var text = [];
(function (){
superagent.get('爬取网站的url')
.end(function(err,pres){
var $ = cheerio.load(pres.text);
var curPageUrls = $('#xy-impcon ul.list-a li a');
console.log(curPageUrls.length)
curPageUrls.each(function(index, elem){
text.push({
title: $(elem).text(),
url: $(elem).attr('href')
})
})
writerStream2.write(JSON.stringify(text),'UTF8');
});
})();
  上面的代码将爬取的内容保存为文件。
  另外,我们还可以在node环境中使用phantomjs的网页模块,模拟浏览器端抓取网页数据,生成网页截图。具体用法后面会介绍

jquery抓取网页内容(使用selenium爬取动态网页信息Pythonselenium自动控制 )

网站优化优采云 发表了文章 • 0 个评论 • 54 次浏览 • 2022-04-04 23:29 • 来自相关话题

  jquery抓取网页内容(使用selenium爬取动态网页信息Pythonselenium自动控制
)
  使用selenium爬取动态网页信息
  python selenium自动控制浏览器抓取网页数据,包括按钮点击、页面跳转、搜索框输入、页面值数据存储、mongodb自动id识别等。
  首先介绍一下Python selenium——一个自动化测试工具,用来控制浏览器对网页的操作。当与爬虫中的 BeautifulSoup 结合使用时,它是无缝的。除了国外的一些异常验证页面,图片验证码我自己写了破解。图片验证码源码,成功率85%。
  使用 conda 管家安装:
  在cmd命令行输入“conda install selenium”进行安装
  还需要安装 Google Chrome Drive 或 Firefox 插件
  设置环境变量
  通过selenium访问百度
  from selenium import webdriver
#打开一个浏览器
browser = webdriver.Chrome()
#准备一个网址
url = 'http://www.baidu.com'
browser.get(url)
#获取元素
login = browser.find_elements_by_class_name('lb')[0]
print(login)
  获取网易云音乐
  
from selenium import webdriver
#打开浏览器
brower = webdriver.Chrome()
url='https://music.163.com/#/discover/toplist'
brower.get(url)
#寻找logo文字
#logo = brower.find_elements_by_class_name('logo')[0]
#print(logo.text)
#一般情况下动态加载的内容都可以找到
#有一种情况就没有
#就是网页内存在网页框架iframe
#需要切换网页的层级
#语法:brower.switch_to.frame(iframe的id或者你提前获取这个对象,放入此处)
#方法一:id
#brower.switch_to.frame('g_iframe')
#方法二:name
#brower.switch_to.frame('contentFrame')
#方法三:提前用变量存iframe
iframe = brower.find_element_by_id('g_iframe')
brower.switch_to.frame(iframe)
#寻找大容器
toplist = brower.find_element_by_id('toplist')
#寻找tbody 通过标签名
tbody = toplist.find_elements_by_tag_name('tbody')[0]
#寻找所有tr
trs = tbody.find_elements_by_tag_name('tr')
dataList = []
for each in trs:
#排名
rank = each.find_elements_by_tag_name('td')[0].find_elements_by_class_name('num')[0].text
musicName = each.find_elements_by_tag_name('td')[1].find_elements_by_class_name('txt')[0].\
find_element_by_tag_name('b').get_attribute('title')
#print(musicName)
singer = each.find_elements_by_tag_name('td')[3].find_elements_by_class_name('text')[0].\
get_attribute('title')
#print(singer)
dataList.append([rank,musicName,singer])
#print(dataList)
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.title = '云音乐飙升榜'
ws.append(['排名','歌名','歌手'])
for data in dataList:
ws.append(data)
wb.save("云音乐飙升榜.xlsx") 查看全部

  jquery抓取网页内容(使用selenium爬取动态网页信息Pythonselenium自动控制
)
  使用selenium爬取动态网页信息
  python selenium自动控制浏览器抓取网页数据,包括按钮点击、页面跳转、搜索框输入、页面值数据存储、mongodb自动id识别等。
  首先介绍一下Python selenium——一个自动化测试工具,用来控制浏览器对网页的操作。当与爬虫中的 BeautifulSoup 结合使用时,它是无缝的。除了国外的一些异常验证页面,图片验证码我自己写了破解。图片验证码源码,成功率85%。
  使用 conda 管家安装:
  在cmd命令行输入“conda install selenium”进行安装
  还需要安装 Google Chrome Drive 或 Firefox 插件
  设置环境变量
  通过selenium访问百度
  from selenium import webdriver
#打开一个浏览器
browser = webdriver.Chrome()
#准备一个网址
url = 'http://www.baidu.com'
browser.get(url)
#获取元素
login = browser.find_elements_by_class_name('lb')[0]
print(login)
  获取网易云音乐
  
from selenium import webdriver
#打开浏览器
brower = webdriver.Chrome()
url='https://music.163.com/#/discover/toplist'
brower.get(url)
#寻找logo文字
#logo = brower.find_elements_by_class_name('logo')[0]
#print(logo.text)
#一般情况下动态加载的内容都可以找到
#有一种情况就没有
#就是网页内存在网页框架iframe
#需要切换网页的层级
#语法:brower.switch_to.frame(iframe的id或者你提前获取这个对象,放入此处)
#方法一:id
#brower.switch_to.frame('g_iframe')
#方法二:name
#brower.switch_to.frame('contentFrame')
#方法三:提前用变量存iframe
iframe = brower.find_element_by_id('g_iframe')
brower.switch_to.frame(iframe)
#寻找大容器
toplist = brower.find_element_by_id('toplist')
#寻找tbody 通过标签名
tbody = toplist.find_elements_by_tag_name('tbody')[0]
#寻找所有tr
trs = tbody.find_elements_by_tag_name('tr')
dataList = []
for each in trs:
#排名
rank = each.find_elements_by_tag_name('td')[0].find_elements_by_class_name('num')[0].text
musicName = each.find_elements_by_tag_name('td')[1].find_elements_by_class_name('txt')[0].\
find_element_by_tag_name('b').get_attribute('title')
#print(musicName)
singer = each.find_elements_by_tag_name('td')[3].find_elements_by_class_name('text')[0].\
get_attribute('title')
#print(singer)
dataList.append([rank,musicName,singer])
#print(dataList)
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.title = '云音乐飙升榜'
ws.append(['排名','歌名','歌手'])
for data in dataList:
ws.append(data)
wb.save("云音乐飙升榜.xlsx")

jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)

网站优化优采云 发表了文章 • 0 个评论 • 53 次浏览 • 2022-04-04 05:11 • 来自相关话题

  jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)
  下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块。
  1. 正则表达式
  如果您是正则表达式的新手,或者需要一些提示,请查看正则表达式 HOWTO 以获得完整的介绍。
  当我们使用正则表达式抓取国家/地区数据时,我们首先尝试匹配元素的内容,如下所示:
  >>> import re
>>> import urllib2<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> re.findall(&#39;(.*?)&#39;, html)<br />
[&#39;/places/static/images/flags/gb.png&#39;, &#39;244,820 square kilometres&#39;, &#39;62,348,447&#39;, &#39;GB&#39;, &#39;United Kingdom&#39;, &#39;London&#39;, &#39;EU&#39;, &#39;.uk&#39;, &#39;GBP&#39;, &#39;Pound&#39;, &#39;44&#39;, &#39;@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA&#39;, &#39;^(([A-Z]\\d{2}[A-Z]{2})|([A-Z]\\d{3}[A-Z]{2})|([A-Z]{2}\\d{2}[A-Z]{2})|([A-Z]{2}\\d{3}[A-Z]{2})|([A-Z]\\d[A-Z]\\d[A-Z]{2})|([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})|(GIR0AA))$&#39;, &#39;en-GB,cy-GB,gd&#39;, &#39;IE &#39;]
>>>
  从以上结果可以看出,标签用于多个国家属性。要隔离 area 属性,我们只需选择其中的第二个元素,如下所示:
  >>> re.findall(&#39;(.*?)&#39;, html)[1]
&#39;244,820 square kilometres&#39;
  虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,该表已更改为删除第二行中的土地面积数据。如果我们现在只抓取数据,我们可以忽略这种未来可能发生的变化。但是,如果我们以后想再次获取这些数据,我们需要一个更健壮的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更加健壮,我们也可以添加它的父元素。由于元素具有 ID 属性,因此它应该是唯一的。
  >>> re.findall(&#39;Area: (.*?)&#39;, html)<br />
[&#39;244,820 square kilometres&#39;]
  这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在标签之间添加额外的空格,或者更改 area_label 等。下面是一个尝试支持这些可能性的改进版本。
  >>> re.findall(&#39;.*?(.*?)&#39;,html)[&#39;244,820 square kilometres&#39;]
  虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有一些细微的布局更改可能会使此正则表达式无法令人满意,例如为标签添加标题属性。
  从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。好在还有一些更好的解决方案,后面会介绍。
  2. 靓汤
  Beautiful Soup 是一个非常流行的 Python 模块。该模块可以解析网页并提供方便的界面来定位内容。如果您还没有安装该模块,可以使用以下命令安装其最新版本(需要先安装pip,请自行百度):
  pip install beautifulsoup4
  使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于大多数网页不是格式良好的 HTML,Beautiful Soup 需要确定它们的实际格式。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。
  <br />Area<br />Population<br />
  如果 Population 列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们在抓取时会得到错误的结果。让我们看看Beautiful Soup是如何处理它的。
  >>> from bs4 import BeautifulSoup
>>> broken_html = &#39;<br />AreaPopulation&#39;<br />
>>> # parse the HTML<br />
>>> soup = BeautifulSoup(broken_html, &#39;html.parser&#39;)<br />
>>> fixed_html = soup.prettify()<br />
>>> print fixed_html<br /><br /><br />
Area<br /><br />
Population<br /><br /><br />
  从上面的执行结果可以看出,Beautiful Soup 能够正确解析缺失的引号并关闭标签。现在我们可以使用 find() 和 find_all() 方法来定位我们需要的元素。
  >>> ul = soup.find(&#39;ul&#39;, attrs={&#39;class&#39;:&#39;country&#39;})<br />
>>> ul.find(&#39;li&#39;) # return just the first match<br />AreaPopulation<br />
>>> ul.find_all(&#39;li&#39;) # return all matches<br />
[AreaPopulation, Population]
  注意:由于不同版本的Python内置库的容错能力存在差异,处理结果可能与上述不同。详情请参阅: 。想知道所有的方法和参数,可以参考 Beautiful Soup 的官方文档
  以下是使用此方法提取样本国家地区数据的完整代码。
  >>> from bs4 import BeautifulSoup<br />>>> import urllib2<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> # locate the area row<br />>>> tr = soup.find(attrs={&#39;id&#39;:&#39;places_area__row&#39;})<br />>>> # locate the area tag<br />>>> td = tr.find(attrs={&#39;class&#39;:&#39;w2p_fw&#39;})<br />>>> area = td.text # extract the text from this tag<br />>>> print area<br />244,820 square kilometres
  此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局中的一些小变化,例如额外的空白和制表符属性,我们不再需要担心它了。
  3. Lxml
  Lxml 是基于 XML 解析库 libxml2 的 Python 包装器。模块用C语言编写,解析速度比Beautiful Soup快,但安装过程比较复杂。最新安装说明可以参考。**
  与 Beautiful Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。以下是使用此模块解析不完整 HTML 的示例:
  >>> import lxml.html<br />
>>> broken_html = &#39;<br />AreaPopulation&#39;
>>> # parse the HTML<br />
>>> tree = lxml.html.fromstring(broken_html)<br />
>>> fixed_html = lxml.html.tostring(tree, pretty_print=True)<br />
>>> print fixed_html<br /><br />Area<br />Population<br />
  同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。
  解析输入后,是时候选择元素了。此时,lxml 有几种不同的方法,例如 XPath 选择器和 Beautiful Soup 之类的 find() 方法。但是,我们将来会使用 CSS 选择器,因为它更简洁,可以在解析动态内容时重用。此外,一些有 jQuery 选择器经验的读者会更熟悉它。
  以下是使用 lxml 的 CSS 选择器提取区域数据的示例代码:
  >>> import urllib2<br />>>> import lxml.html<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> tree = lxml.html.fromstring(html)<br />>>> td = tree.cssselect(&#39;tr#places_area__row > td.w2p_fw&#39;)[0] # *行代码<br />>>> area = td.text_content()<br />>>> print area
244,820 square kilometres
  *行代码会先找到ID为places_area__row的表格行元素,然后选择类为w2p_fw的表格数据子标签。
  CSS 选择器表示用于选择元素的模式。以下是一些常用选择器的示例:
  选择所有标签: *<br />
选择 标签: a<br />
选择所有 class="link" 的元素: .link<br />
选择 class="link" 的 标签: a.link<br />
选择 id="home" 的 标签: a#home<br />
选择父元素为 标签的所有 子标签: a > span<br />
选择 标签内部的所有 标签: a span <br />
选择 title 属性为"Home"的所有 标签: a[title=Home]
  W3C 在
  Lxml 已经实现了大部分 CSS3 属性,其不支持的功能可以在: .
  注意:lxml 的内部实现实际上将 CSS 选择器转换为等效的 XPath 选择器。
  4. 性能比较
  在下面的代码中,每个爬虫会执行1000次,每次执行都会检查爬取结果是否正确,然后打印总时间。
  # -*- coding: utf-8 -*-<br /><br />import csv<br />import time<br />import urllib2<br />import re<br />import timeit<br />from bs4 import BeautifulSoup<br />import lxml.html<br /><br />
FIELDS = (&#39;area&#39;, &#39;population&#39;, &#39;iso&#39;, &#39;country&#39;, &#39;capital&#39;, &#39;continent&#39;, &#39;tld&#39;, &#39;currency_code&#39;, &#39;currency_name&#39;, &#39;phone&#39;, &#39;postal_code_format&#39;, &#39;postal_code_regex&#39;, &#39;languages&#39;, &#39;neighbours&#39;)<br /><br />def regex_scraper(html):<br /><br />
results = {}<br />for field in FIELDS:<br />
results[field] = re.search(&#39;.*?(.*?)&#39;.format(field), html).groups()[0]<br />return results<br /><br />def beautiful_soup_scraper(html):<br />
soup = BeautifulSoup(html, &#39;html.parser&#39;) <br />
results = {}<br />for field in FIELDS:<br />
results[field] = soup.find(&#39;table&#39;).find(&#39;tr&#39;, id=&#39;places_{}__row&#39;.format(field)).find(&#39;td&#39;, class_=&#39;w2p_fw&#39;).text<br />return results<br /><br />def lxml_scraper(html):<br />
tree = lxml.html.fromstring(html)<br />
results = {}<br />for field in FIELDS:<br />
results[field] = tree.cssselect(&#39;table > tr#places_{}__row > td.w2p_fw&#39;.format(field))[0].text_content()<br />return results<br /><br />def main():
times = {}
html = urllib2.urlopen(&#39;http://example.webscraping.com ... %2339;).read()<br />
NUM_ITERATIONS = 1000 # number of times to test each scraper<br />for name, scraper in (&#39;Regular expressions&#39;, regex_scraper), (&#39;Beautiful Soup&#39;, beautiful_soup_scraper), (&#39;Lxml&#39;, lxml_scraper):<br />
times[name] = []<br /># record start time of scrape<br />
start = time.time()<br />for i in range(NUM_ITERATIONS):<br />if scraper == regex_scraper:<br /># the regular expression module will cache results<br /># so need to purge this cache for meaningful timings<br />
re.purge() # *行代码<br />
result = scraper(html)<br /><br /># check scraped result is as expected<br />assert(result[&#39;area&#39;] == &#39;244,820 square kilometres&#39;)<br />
times[name].append(time.time() - start)<br /># record end time of scrape and output the total<br />
end = time.time()<br />print &#39;{}: {:.2f} seconds&#39;.format(name, end - start)<br /><br />
writer = csv.writer(open(&#39;times.csv&#39;, &#39;w&#39;))<br />
header = sorted(times.keys())<br />
writer.writerow(header)<br />for row in zip(*[times[scraper] for scraper in header]):<br />
writer.writerow(row)<br /><br />if __name__ == &#39;__main__&#39;:<br />
main()
  请注意,我们在 *line 代码中调用了 re.purge() 方法。默认情况下,正则表达式会缓存搜索结果,公平起见,我们需要使用这种方法来清除缓存。
  这是在我的计算机上运行脚本的结果:
  
  由于硬件条件的不同,不同计算机的执行结果也会有一定的差异。但是,每种方法之间的相对差异应该具有可比性。从结果可以看出,Beautiful Soup 在爬取我们的示例网页时比其他两种方法慢 7 倍以上。事实上,这个结果是意料之中的,因为 lxml 和正则表达式模块是用 C 编写的,而 Beautiful Soup 是用纯 Python 编写的。一个有趣的事实是 lxml 的性能与正则表达式差不多。由于 lxml 必须在搜索元素之前将输入解析为内部格式,因此会产生额外的开销。当爬取同一个网页的多个特征时,这个初始解析的开销会减少,lxml会更有竞争力,所以lxml是一个强大的模块。
  5. 总结
  三种网页抓取方式的优缺点:
  抓取方式 性能 使用难度 安装难度
  正则表达式
  快的
  困难
  简单(内置模块)
  美丽的汤
  慢
  简单的
  简单(纯 Python)
  lxml
  快的
  简单的
  比较困难
  如果您的爬虫的瓶颈是下载页面,而不是提取数据,那么使用较慢的方法(如 Beautiful Soup)不是问题。正则表达式在一次提取中非常有用,除了避免解析整个网页的开销之外,如果你只需要抓取少量数据并想避免额外的依赖,那么正则表达式可能更适合. 但是,总的来说,lxml 是抓取数据的最佳选择,因为它不仅速度更快,功能更强大,而正则表达式和 Beautiful Soup 仅在某些特定场景下才有用。 查看全部

  jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)
  下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块。
  1. 正则表达式
  如果您是正则表达式的新手,或者需要一些提示,请查看正则表达式 HOWTO 以获得完整的介绍。
  当我们使用正则表达式抓取国家/地区数据时,我们首先尝试匹配元素的内容,如下所示:
  >>> import re
>>> import urllib2<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> re.findall(&#39;(.*?)&#39;, html)<br />
[&#39;/places/static/images/flags/gb.png&#39;, &#39;244,820 square kilometres&#39;, &#39;62,348,447&#39;, &#39;GB&#39;, &#39;United Kingdom&#39;, &#39;London&#39;, &#39;EU&#39;, &#39;.uk&#39;, &#39;GBP&#39;, &#39;Pound&#39;, &#39;44&#39;, &#39;@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA&#39;, &#39;^(([A-Z]\\d{2}[A-Z]{2})|([A-Z]\\d{3}[A-Z]{2})|([A-Z]{2}\\d{2}[A-Z]{2})|([A-Z]{2}\\d{3}[A-Z]{2})|([A-Z]\\d[A-Z]\\d[A-Z]{2})|([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})|(GIR0AA))$&#39;, &#39;en-GB,cy-GB,gd&#39;, &#39;IE &#39;]
>>>
  从以上结果可以看出,标签用于多个国家属性。要隔离 area 属性,我们只需选择其中的第二个元素,如下所示:
  >>> re.findall(&#39;(.*?)&#39;, html)[1]
&#39;244,820 square kilometres&#39;
  虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,该表已更改为删除第二行中的土地面积数据。如果我们现在只抓取数据,我们可以忽略这种未来可能发生的变化。但是,如果我们以后想再次获取这些数据,我们需要一个更健壮的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更加健壮,我们也可以添加它的父元素。由于元素具有 ID 属性,因此它应该是唯一的。
  >>> re.findall(&#39;Area: (.*?)&#39;, html)<br />
[&#39;244,820 square kilometres&#39;]
  这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在标签之间添加额外的空格,或者更改 area_label 等。下面是一个尝试支持这些可能性的改进版本。
  >>> re.findall(&#39;.*?(.*?)&#39;,html)[&#39;244,820 square kilometres&#39;]
  虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有一些细微的布局更改可能会使此正则表达式无法令人满意,例如为标签添加标题属性。
  从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。好在还有一些更好的解决方案,后面会介绍。
  2. 靓汤
  Beautiful Soup 是一个非常流行的 Python 模块。该模块可以解析网页并提供方便的界面来定位内容。如果您还没有安装该模块,可以使用以下命令安装其最新版本(需要先安装pip,请自行百度):
  pip install beautifulsoup4
  使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于大多数网页不是格式良好的 HTML,Beautiful Soup 需要确定它们的实际格式。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。
  <br />Area<br />Population<br />
  如果 Population 列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们在抓取时会得到错误的结果。让我们看看Beautiful Soup是如何处理它的。
  >>> from bs4 import BeautifulSoup
>>> broken_html = &#39;<br />AreaPopulation&#39;<br />
>>> # parse the HTML<br />
>>> soup = BeautifulSoup(broken_html, &#39;html.parser&#39;)<br />
>>> fixed_html = soup.prettify()<br />
>>> print fixed_html<br /><br /><br />
Area<br /><br />
Population<br /><br /><br />
  从上面的执行结果可以看出,Beautiful Soup 能够正确解析缺失的引号并关闭标签。现在我们可以使用 find() 和 find_all() 方法来定位我们需要的元素。
  >>> ul = soup.find(&#39;ul&#39;, attrs={&#39;class&#39;:&#39;country&#39;})<br />
>>> ul.find(&#39;li&#39;) # return just the first match<br />AreaPopulation<br />
>>> ul.find_all(&#39;li&#39;) # return all matches<br />
[AreaPopulation, Population]
  注意:由于不同版本的Python内置库的容错能力存在差异,处理结果可能与上述不同。详情请参阅: 。想知道所有的方法和参数,可以参考 Beautiful Soup 的官方文档
  以下是使用此方法提取样本国家地区数据的完整代码。
  >>> from bs4 import BeautifulSoup<br />>>> import urllib2<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> # locate the area row<br />>>> tr = soup.find(attrs={&#39;id&#39;:&#39;places_area__row&#39;})<br />>>> # locate the area tag<br />>>> td = tr.find(attrs={&#39;class&#39;:&#39;w2p_fw&#39;})<br />>>> area = td.text # extract the text from this tag<br />>>> print area<br />244,820 square kilometres
  此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局中的一些小变化,例如额外的空白和制表符属性,我们不再需要担心它了。
  3. Lxml
  Lxml 是基于 XML 解析库 libxml2 的 Python 包装器。模块用C语言编写,解析速度比Beautiful Soup快,但安装过程比较复杂。最新安装说明可以参考。**
  与 Beautiful Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。以下是使用此模块解析不完整 HTML 的示例:
  >>> import lxml.html<br />
>>> broken_html = &#39;<br />AreaPopulation&#39;
>>> # parse the HTML<br />
>>> tree = lxml.html.fromstring(broken_html)<br />
>>> fixed_html = lxml.html.tostring(tree, pretty_print=True)<br />
>>> print fixed_html<br /><br />Area<br />Population<br />
  同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。
  解析输入后,是时候选择元素了。此时,lxml 有几种不同的方法,例如 XPath 选择器和 Beautiful Soup 之类的 find() 方法。但是,我们将来会使用 CSS 选择器,因为它更简洁,可以在解析动态内容时重用。此外,一些有 jQuery 选择器经验的读者会更熟悉它。
  以下是使用 lxml 的 CSS 选择器提取区域数据的示例代码:
  >>> import urllib2<br />>>> import lxml.html<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> tree = lxml.html.fromstring(html)<br />>>> td = tree.cssselect(&#39;tr#places_area__row > td.w2p_fw&#39;)[0] # *行代码<br />>>> area = td.text_content()<br />>>> print area
244,820 square kilometres
  *行代码会先找到ID为places_area__row的表格行元素,然后选择类为w2p_fw的表格数据子标签。
  CSS 选择器表示用于选择元素的模式。以下是一些常用选择器的示例:
  选择所有标签: *<br />
选择 标签: a<br />
选择所有 class="link" 的元素: .link<br />
选择 class="link" 的 标签: a.link<br />
选择 id="home" 的 标签: a#home<br />
选择父元素为 标签的所有 子标签: a > span<br />
选择 标签内部的所有 标签: a span <br />
选择 title 属性为"Home"的所有 标签: a[title=Home]
  W3C 在
  Lxml 已经实现了大部分 CSS3 属性,其不支持的功能可以在: .
  注意:lxml 的内部实现实际上将 CSS 选择器转换为等效的 XPath 选择器。
  4. 性能比较
  在下面的代码中,每个爬虫会执行1000次,每次执行都会检查爬取结果是否正确,然后打印总时间。
  # -*- coding: utf-8 -*-<br /><br />import csv<br />import time<br />import urllib2<br />import re<br />import timeit<br />from bs4 import BeautifulSoup<br />import lxml.html<br /><br />
FIELDS = (&#39;area&#39;, &#39;population&#39;, &#39;iso&#39;, &#39;country&#39;, &#39;capital&#39;, &#39;continent&#39;, &#39;tld&#39;, &#39;currency_code&#39;, &#39;currency_name&#39;, &#39;phone&#39;, &#39;postal_code_format&#39;, &#39;postal_code_regex&#39;, &#39;languages&#39;, &#39;neighbours&#39;)<br /><br />def regex_scraper(html):<br /><br />
results = {}<br />for field in FIELDS:<br />
results[field] = re.search(&#39;.*?(.*?)&#39;.format(field), html).groups()[0]<br />return results<br /><br />def beautiful_soup_scraper(html):<br />
soup = BeautifulSoup(html, &#39;html.parser&#39;) <br />
results = {}<br />for field in FIELDS:<br />
results[field] = soup.find(&#39;table&#39;).find(&#39;tr&#39;, id=&#39;places_{}__row&#39;.format(field)).find(&#39;td&#39;, class_=&#39;w2p_fw&#39;).text<br />return results<br /><br />def lxml_scraper(html):<br />
tree = lxml.html.fromstring(html)<br />
results = {}<br />for field in FIELDS:<br />
results[field] = tree.cssselect(&#39;table > tr#places_{}__row > td.w2p_fw&#39;.format(field))[0].text_content()<br />return results<br /><br />def main():
times = {}
html = urllib2.urlopen(&#39;http://example.webscraping.com ... %2339;).read()<br />
NUM_ITERATIONS = 1000 # number of times to test each scraper<br />for name, scraper in (&#39;Regular expressions&#39;, regex_scraper), (&#39;Beautiful Soup&#39;, beautiful_soup_scraper), (&#39;Lxml&#39;, lxml_scraper):<br />
times[name] = []<br /># record start time of scrape<br />
start = time.time()<br />for i in range(NUM_ITERATIONS):<br />if scraper == regex_scraper:<br /># the regular expression module will cache results<br /># so need to purge this cache for meaningful timings<br />
re.purge() # *行代码<br />
result = scraper(html)<br /><br /># check scraped result is as expected<br />assert(result[&#39;area&#39;] == &#39;244,820 square kilometres&#39;)<br />
times[name].append(time.time() - start)<br /># record end time of scrape and output the total<br />
end = time.time()<br />print &#39;{}: {:.2f} seconds&#39;.format(name, end - start)<br /><br />
writer = csv.writer(open(&#39;times.csv&#39;, &#39;w&#39;))<br />
header = sorted(times.keys())<br />
writer.writerow(header)<br />for row in zip(*[times[scraper] for scraper in header]):<br />
writer.writerow(row)<br /><br />if __name__ == &#39;__main__&#39;:<br />
main()
  请注意,我们在 *line 代码中调用了 re.purge() 方法。默认情况下,正则表达式会缓存搜索结果,公平起见,我们需要使用这种方法来清除缓存。
  这是在我的计算机上运行脚本的结果:
  
  由于硬件条件的不同,不同计算机的执行结果也会有一定的差异。但是,每种方法之间的相对差异应该具有可比性。从结果可以看出,Beautiful Soup 在爬取我们的示例网页时比其他两种方法慢 7 倍以上。事实上,这个结果是意料之中的,因为 lxml 和正则表达式模块是用 C 编写的,而 Beautiful Soup 是用纯 Python 编写的。一个有趣的事实是 lxml 的性能与正则表达式差不多。由于 lxml 必须在搜索元素之前将输入解析为内部格式,因此会产生额外的开销。当爬取同一个网页的多个特征时,这个初始解析的开销会减少,lxml会更有竞争力,所以lxml是一个强大的模块。
  5. 总结
  三种网页抓取方式的优缺点:
  抓取方式 性能 使用难度 安装难度
  正则表达式
  快的
  困难
  简单(内置模块)
  美丽的汤
  慢
  简单的
  简单(纯 Python)
  lxml
  快的
  简单的
  比较困难
  如果您的爬虫的瓶颈是下载页面,而不是提取数据,那么使用较慢的方法(如 Beautiful Soup)不是问题。正则表达式在一次提取中非常有用,除了避免解析整个网页的开销之外,如果你只需要抓取少量数据并想避免额外的依赖,那么正则表达式可能更适合. 但是,总的来说,lxml 是抓取数据的最佳选择,因为它不仅速度更快,功能更强大,而正则表达式和 Beautiful Soup 仅在某些特定场景下才有用。

jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)

网站优化优采云 发表了文章 • 0 个评论 • 385 次浏览 • 2022-04-03 03:07 • 来自相关话题

  jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)
  下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块。
  1. 正则表达式
  如果您是正则表达式的新手,或者需要一些提示,请查看正则表达式 HOWTO 以获得完整的介绍。
  当我们使用正则表达式抓取国家/地区数据时,我们首先尝试匹配元素的内容,如下所示:
  >>> import re
>>> import urllib2
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> re.findall(&#39;(.*?)&#39;, html)
[&#39;/places/static/images/flags/gb.png&#39;, &#39;244,820 square kilometres&#39;, &#39;62,348,447&#39;, &#39;GB&#39;, &#39;United Kingdom&#39;, &#39;London&#39;, &#39;EU&#39;, &#39;.uk&#39;, &#39;GBP&#39;, &#39;Pound&#39;, &#39;44&#39;, &#39;@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA&#39;, &#39;^(([A-Z]\\d{2}[A-Z]{2})|([A-Z]\\d{3}[A-Z]{2})|([A-Z]{2}\\d{2}[A-Z]{2})|([A-Z]{2}\\d{3}[A-Z]{2})|([A-Z]\\d[A-Z]\\d[A-Z]{2})|([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})|(GIR0AA))$&#39;, &#39;en-GB,cy-GB,gd&#39;, &#39;IE &#39;]
>>>
  从以上结果可以看出,标签用于多个国家属性。要隔离 area 属性,我们只需选择其中的第二个元素,如下所示:
  >>> re.findall(&#39;(.*?)&#39;, html)[1]
&#39;244,820 square kilometres&#39;
  虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,该表已更改为删除第二行中的土地面积数据。如果我们现在只抓取数据,我们可以忽略这种未来可能发生的变化。但是,如果我们以后想再次获取这些数据,我们需要一个更健壮的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更加健壮,我们也可以添加它的父元素。由于元素具有 ID 属性,因此它应该是唯一的。
  >>> re.findall(&#39;Area: (.*?)&#39;, html)
[&#39;244,820 square kilometres&#39;]
  这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在标签之间添加额外的空格,或者更改 area_label 等。下面是一个改进版本,试图支持这些可能性。
  >>> re.findall(&#39;.*?(.*?)&#39;,html)[&#39;244,820 square kilometres&#39;]
  虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有一些细微的布局更改可能会使此正则表达式无法令人满意,例如为标签添加标题属性。
  从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。好在还有一些更好的解决方案,后面会介绍。
  2. 靓汤
  Beautiful Soup 是一个非常流行的 Python 模块。该模块可以解析网页并提供方便的界面来定位内容。如果您还没有安装该模块,可以使用以下命令安装其最新版本(需要先安装pip,请自行百度):
  pip install beautifulsoup4
  使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于大多数网页不是格式良好的 HTML,Beautiful Soup 需要确定它们的实际格式。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。
  
Area
Population
  如果 Population 列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们在抓取时会得到错误的结果。让我们看看Beautiful Soup是如何处理它的。
  >>> from bs4 import BeautifulSoup
>>> broken_html = &#39;AreaPopulation&#39;
>>> # parse the HTML
>>> soup = BeautifulSoup(broken_html, &#39;html.parser&#39;)
>>> fixed_html = soup.prettify()
>>> print fixed_html

Area

Population


  从上面的执行结果可以看出,Beautiful Soup 能够正确解析缺失的引号并关闭标签。现在我们可以使用 find() 和 find_all() 方法来定位我们需要的元素。
  >>> ul = soup.find(&#39;ul&#39;, attrs={&#39;class&#39;:&#39;country&#39;})
>>> ul.find(&#39;li&#39;) # return just the first match
AreaPopulation
>>> ul.find_all(&#39;li&#39;) # return all matches
[AreaPopulation, Population]
  注意:由于不同版本的Python内置库容错能力不同,处理结果可能与上述不同。详情请参阅: 。想知道所有的方法和参数,可以参考 Beautiful Soup 的官方文档
  以下是使用此方法提取样本国家地区数据的完整代码。
  >>> from bs4 import BeautifulSoup
>>> import urllib2
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> # locate the area row
>>> tr = soup.find(attrs={&#39;id&#39;:&#39;places_area__row&#39;})
>>> # locate the area tag
>>> td = tr.find(attrs={&#39;class&#39;:&#39;w2p_fw&#39;})
>>> area = td.text # extract the text from this tag
>>> print area
244,820 square kilometres
  此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局中的一些小变化,例如额外的空白和制表符属性,我们不再需要担心它了。
  3. Lxml
  Lxml 是基于 XML 解析库 libxml2 的 Python 包装器。模块用C语言编写,解析速度比Beautiful Soup快,但安装过程比较复杂。最新安装说明可以参考。**
  与 Beautiful Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。以下是使用此模块解析不完整 HTML 的示例:
  >>> import lxml.html
>>> broken_html = &#39;AreaPopulation&#39;
>>> # parse the HTML
>>> tree = lxml.html.fromstring(broken_html)
>>> fixed_html = lxml.html.tostring(tree, pretty_print=True)
>>> print fixed_html
Area
Population
  同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。
  解析输入后,是时候选择元素了。此时,lxml 有几种不同的方法,例如 XPath 选择器和 Beautiful Soup 之类的 find() 方法。但是,我们将来会使用 CSS 选择器,因为它更简洁,可以在解析动态内容时重用。此外,一些有 jQuery 选择器经验的读者会更熟悉它。
  以下是使用 lxml 的 CSS 选择器提取区域数据的示例代码:
  >>> import urllib2
>>> import lxml.html
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> tree = lxml.html.fromstring(html)
>>> td = tree.cssselect(&#39;tr#places_area__row > td.w2p_fw&#39;)[0] # *行代码
>>> area = td.text_content()
>>> print area
244,820 square kilometres
  *行代码会先找到ID为places_area__row的表格行元素,然后选择类为w2p_fw的表格数据子标签。
  CSS 选择器表示用于选择元素的模式。以下是一些常用选择器的示例:
  选择所有标签: *
选择 标签: a
选择所有 class="link" 的元素: .link
选择 class="link" 的 标签: a.link
选择 id="home" 的 标签: a#home
选择父元素为 标签的所有 子标签: a > span
选择 标签内部的所有 标签: a span
选择 title 属性为"Home"的所有 标签: a[title=Home]
  W3C 在
  Lxml 已经实现了大部分 CSS3 属性,其不支持的功能可以在: .
  注意:lxml 的内部实现实际上将 CSS 选择器转换为等效的 XPath 选择器。
  4. 性能比较
  在下面的代码中,每个爬虫会执行1000次,每次执行都会检查爬取结果是否正确,然后打印总时间。
  # -*- coding: utf-8 -*-
import csv
import time
import urllib2
import re
import timeit
from bs4 import BeautifulSoup
import lxml.html
FIELDS = (&#39;area&#39;, &#39;population&#39;, &#39;iso&#39;, &#39;country&#39;, &#39;capital&#39;, &#39;continent&#39;, &#39;tld&#39;, &#39;currency_code&#39;, &#39;currency_name&#39;, &#39;phone&#39;, &#39;postal_code_format&#39;, &#39;postal_code_regex&#39;, &#39;languages&#39;, &#39;neighbours&#39;)
def regex_scraper(html):
results = {}
for field in FIELDS:
results[field] = re.search(&#39;.*?(.*?)&#39;.format(field), html).groups()[0]
return results
def beautiful_soup_scraper(html):
soup = BeautifulSoup(html, &#39;html.parser&#39;)
results = {}
for field in FIELDS:
results[field] = soup.find(&#39;table&#39;).find(&#39;tr&#39;, id=&#39;places_{}__row&#39;.format(field)).find(&#39;td&#39;, class_=&#39;w2p_fw&#39;).text
return results
def lxml_scraper(html):
tree = lxml.html.fromstring(html)
results = {}
for field in FIELDS:
results[field] = tree.cssselect(&#39;table > tr#places_{}__row > td.w2p_fw&#39;.format(field))[0].text_content()
return results
def main():
times = {}
html = urllib2.urlopen(&#39;http://example.webscraping.com ... %2339;).read()
NUM_ITERATIONS = 1000 # number of times to test each scraper
for name, scraper in (&#39;Regular expressions&#39;, regex_scraper), (&#39;Beautiful Soup&#39;, beautiful_soup_scraper), (&#39;Lxml&#39;, lxml_scraper):
times[name] = []
# record start time of scrape
start = time.time()
for i in range(NUM_ITERATIONS):
if scraper == regex_scraper:
# the regular expression module will cache results
# so need to purge this cache for meaningful timings
re.purge() # *行代码
result = scraper(html)
# check scraped result is as expected
assert(result[&#39;area&#39;] == &#39;244,820 square kilometres&#39;)
times[name].append(time.time() - start)
# record end time of scrape and output the total
end = time.time()
print &#39;{}: {:.2f} seconds&#39;.format(name, end - start)
writer = csv.writer(open(&#39;times.csv&#39;, &#39;w&#39;))
header = sorted(times.keys())
writer.writerow(header)
for row in zip(*[times[scraper] for scraper in header]):
writer.writerow(row)
if __name__ == &#39;__main__&#39;:
main()
  请注意,我们在 *line 代码中调用了 re.purge() 方法。默认情况下,正则表达式会缓存搜索结果,公平起见,我们需要使用这种方法来清除缓存。
  这是在我的计算机上运行脚本的结果:
  
  由于硬件条件的不同,不同计算机的执行结果也会有一定的差异。但是,每种方法之间的相对差异应该具有可比性。从结果可以看出,Beautiful Soup 在爬取我们的示例网页时比其他两种方法慢 7 倍以上。事实上,这个结果是意料之中的,因为 lxml 和正则表达式模块是用 C 编写的,而 Beautiful Soup 是用纯 Python 编写的。一个有趣的事实是 lxml 的性能与正则表达式差不多。由于 lxml 必须在搜索元素之前将输入解析为内部格式,因此会产生额外的开销。当爬取同一个网页的多个特征时,这个初始解析的开销会减少,lxml会更有竞争力,所以lxml是一个强大的模块。
  5. 总结
  三种网页抓取方式的优缺点:
  抓取方式 性能 使用难度 安装难度
  正则表达式
  快的
  困难
  简单(内置模块)
  美丽的汤
  慢
  简单的
  简单(纯 Python)
  lxml
  快的
  简单的
  比较困难
  如果您的爬虫的瓶颈是下载页面,而不是提取数据,那么使用较慢的方法(如 Beautiful Soup)不是问题。正则表达式在一次提取中非常有用,除了避免解析整个网页的开销之外,如果你只需要抓取少量数据并想避免额外的依赖,那么正则表达式可能更适合. 但是,一般来说,lxml 是抓取数据的最佳选择,因为它不仅速度更快,功能更强大,而正则表达式和 Beautiful Soup 仅在某些特定场景下才有用。 查看全部

  jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)
  下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块。
  1. 正则表达式
  如果您是正则表达式的新手,或者需要一些提示,请查看正则表达式 HOWTO 以获得完整的介绍。
  当我们使用正则表达式抓取国家/地区数据时,我们首先尝试匹配元素的内容,如下所示:
  >>> import re
>>> import urllib2
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> re.findall(&#39;(.*?)&#39;, html)
[&#39;/places/static/images/flags/gb.png&#39;, &#39;244,820 square kilometres&#39;, &#39;62,348,447&#39;, &#39;GB&#39;, &#39;United Kingdom&#39;, &#39;London&#39;, &#39;EU&#39;, &#39;.uk&#39;, &#39;GBP&#39;, &#39;Pound&#39;, &#39;44&#39;, &#39;@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA&#39;, &#39;^(([A-Z]\\d{2}[A-Z]{2})|([A-Z]\\d{3}[A-Z]{2})|([A-Z]{2}\\d{2}[A-Z]{2})|([A-Z]{2}\\d{3}[A-Z]{2})|([A-Z]\\d[A-Z]\\d[A-Z]{2})|([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})|(GIR0AA))$&#39;, &#39;en-GB,cy-GB,gd&#39;, &#39;IE &#39;]
>>>
  从以上结果可以看出,标签用于多个国家属性。要隔离 area 属性,我们只需选择其中的第二个元素,如下所示:
  >>> re.findall(&#39;(.*?)&#39;, html)[1]
&#39;244,820 square kilometres&#39;
  虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,该表已更改为删除第二行中的土地面积数据。如果我们现在只抓取数据,我们可以忽略这种未来可能发生的变化。但是,如果我们以后想再次获取这些数据,我们需要一个更健壮的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更加健壮,我们也可以添加它的父元素。由于元素具有 ID 属性,因此它应该是唯一的。
  >>> re.findall(&#39;Area: (.*?)&#39;, html)
[&#39;244,820 square kilometres&#39;]
  这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在标签之间添加额外的空格,或者更改 area_label 等。下面是一个改进版本,试图支持这些可能性。
  >>> re.findall(&#39;.*?(.*?)&#39;,html)[&#39;244,820 square kilometres&#39;]
  虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有一些细微的布局更改可能会使此正则表达式无法令人满意,例如为标签添加标题属性。
  从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。好在还有一些更好的解决方案,后面会介绍。
  2. 靓汤
  Beautiful Soup 是一个非常流行的 Python 模块。该模块可以解析网页并提供方便的界面来定位内容。如果您还没有安装该模块,可以使用以下命令安装其最新版本(需要先安装pip,请自行百度):
  pip install beautifulsoup4
  使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于大多数网页不是格式良好的 HTML,Beautiful Soup 需要确定它们的实际格式。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。
  
Area
Population
  如果 Population 列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们在抓取时会得到错误的结果。让我们看看Beautiful Soup是如何处理它的。
  >>> from bs4 import BeautifulSoup
>>> broken_html = &#39;AreaPopulation&#39;
>>> # parse the HTML
>>> soup = BeautifulSoup(broken_html, &#39;html.parser&#39;)
>>> fixed_html = soup.prettify()
>>> print fixed_html

Area

Population


  从上面的执行结果可以看出,Beautiful Soup 能够正确解析缺失的引号并关闭标签。现在我们可以使用 find() 和 find_all() 方法来定位我们需要的元素。
  >>> ul = soup.find(&#39;ul&#39;, attrs={&#39;class&#39;:&#39;country&#39;})
>>> ul.find(&#39;li&#39;) # return just the first match
AreaPopulation
>>> ul.find_all(&#39;li&#39;) # return all matches
[AreaPopulation, Population]
  注意:由于不同版本的Python内置库容错能力不同,处理结果可能与上述不同。详情请参阅: 。想知道所有的方法和参数,可以参考 Beautiful Soup 的官方文档
  以下是使用此方法提取样本国家地区数据的完整代码。
  >>> from bs4 import BeautifulSoup
>>> import urllib2
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> # locate the area row
>>> tr = soup.find(attrs={&#39;id&#39;:&#39;places_area__row&#39;})
>>> # locate the area tag
>>> td = tr.find(attrs={&#39;class&#39;:&#39;w2p_fw&#39;})
>>> area = td.text # extract the text from this tag
>>> print area
244,820 square kilometres
  此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局中的一些小变化,例如额外的空白和制表符属性,我们不再需要担心它了。
  3. Lxml
  Lxml 是基于 XML 解析库 libxml2 的 Python 包装器。模块用C语言编写,解析速度比Beautiful Soup快,但安装过程比较复杂。最新安装说明可以参考。**
  与 Beautiful Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。以下是使用此模块解析不完整 HTML 的示例:
  >>> import lxml.html
>>> broken_html = &#39;AreaPopulation&#39;
>>> # parse the HTML
>>> tree = lxml.html.fromstring(broken_html)
>>> fixed_html = lxml.html.tostring(tree, pretty_print=True)
>>> print fixed_html
Area
Population
  同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。
  解析输入后,是时候选择元素了。此时,lxml 有几种不同的方法,例如 XPath 选择器和 Beautiful Soup 之类的 find() 方法。但是,我们将来会使用 CSS 选择器,因为它更简洁,可以在解析动态内容时重用。此外,一些有 jQuery 选择器经验的读者会更熟悉它。
  以下是使用 lxml 的 CSS 选择器提取区域数据的示例代码:
  >>> import urllib2
>>> import lxml.html
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> tree = lxml.html.fromstring(html)
>>> td = tree.cssselect(&#39;tr#places_area__row > td.w2p_fw&#39;)[0] # *行代码
>>> area = td.text_content()
>>> print area
244,820 square kilometres
  *行代码会先找到ID为places_area__row的表格行元素,然后选择类为w2p_fw的表格数据子标签。
  CSS 选择器表示用于选择元素的模式。以下是一些常用选择器的示例:
  选择所有标签: *
选择 标签: a
选择所有 class="link" 的元素: .link
选择 class="link" 的 标签: a.link
选择 id="home" 的 标签: a#home
选择父元素为 标签的所有 子标签: a > span
选择 标签内部的所有 标签: a span
选择 title 属性为"Home"的所有 标签: a[title=Home]
  W3C 在
  Lxml 已经实现了大部分 CSS3 属性,其不支持的功能可以在: .
  注意:lxml 的内部实现实际上将 CSS 选择器转换为等效的 XPath 选择器。
  4. 性能比较
  在下面的代码中,每个爬虫会执行1000次,每次执行都会检查爬取结果是否正确,然后打印总时间。
  # -*- coding: utf-8 -*-
import csv
import time
import urllib2
import re
import timeit
from bs4 import BeautifulSoup
import lxml.html
FIELDS = (&#39;area&#39;, &#39;population&#39;, &#39;iso&#39;, &#39;country&#39;, &#39;capital&#39;, &#39;continent&#39;, &#39;tld&#39;, &#39;currency_code&#39;, &#39;currency_name&#39;, &#39;phone&#39;, &#39;postal_code_format&#39;, &#39;postal_code_regex&#39;, &#39;languages&#39;, &#39;neighbours&#39;)
def regex_scraper(html):
results = {}
for field in FIELDS:
results[field] = re.search(&#39;.*?(.*?)&#39;.format(field), html).groups()[0]
return results
def beautiful_soup_scraper(html):
soup = BeautifulSoup(html, &#39;html.parser&#39;)
results = {}
for field in FIELDS:
results[field] = soup.find(&#39;table&#39;).find(&#39;tr&#39;, id=&#39;places_{}__row&#39;.format(field)).find(&#39;td&#39;, class_=&#39;w2p_fw&#39;).text
return results
def lxml_scraper(html):
tree = lxml.html.fromstring(html)
results = {}
for field in FIELDS:
results[field] = tree.cssselect(&#39;table > tr#places_{}__row > td.w2p_fw&#39;.format(field))[0].text_content()
return results
def main():
times = {}
html = urllib2.urlopen(&#39;http://example.webscraping.com ... %2339;).read()
NUM_ITERATIONS = 1000 # number of times to test each scraper
for name, scraper in (&#39;Regular expressions&#39;, regex_scraper), (&#39;Beautiful Soup&#39;, beautiful_soup_scraper), (&#39;Lxml&#39;, lxml_scraper):
times[name] = []
# record start time of scrape
start = time.time()
for i in range(NUM_ITERATIONS):
if scraper == regex_scraper:
# the regular expression module will cache results
# so need to purge this cache for meaningful timings
re.purge() # *行代码
result = scraper(html)
# check scraped result is as expected
assert(result[&#39;area&#39;] == &#39;244,820 square kilometres&#39;)
times[name].append(time.time() - start)
# record end time of scrape and output the total
end = time.time()
print &#39;{}: {:.2f} seconds&#39;.format(name, end - start)
writer = csv.writer(open(&#39;times.csv&#39;, &#39;w&#39;))
header = sorted(times.keys())
writer.writerow(header)
for row in zip(*[times[scraper] for scraper in header]):
writer.writerow(row)
if __name__ == &#39;__main__&#39;:
main()
  请注意,我们在 *line 代码中调用了 re.purge() 方法。默认情况下,正则表达式会缓存搜索结果,公平起见,我们需要使用这种方法来清除缓存。
  这是在我的计算机上运行脚本的结果:
  
  由于硬件条件的不同,不同计算机的执行结果也会有一定的差异。但是,每种方法之间的相对差异应该具有可比性。从结果可以看出,Beautiful Soup 在爬取我们的示例网页时比其他两种方法慢 7 倍以上。事实上,这个结果是意料之中的,因为 lxml 和正则表达式模块是用 C 编写的,而 Beautiful Soup 是用纯 Python 编写的。一个有趣的事实是 lxml 的性能与正则表达式差不多。由于 lxml 必须在搜索元素之前将输入解析为内部格式,因此会产生额外的开销。当爬取同一个网页的多个特征时,这个初始解析的开销会减少,lxml会更有竞争力,所以lxml是一个强大的模块。
  5. 总结
  三种网页抓取方式的优缺点:
  抓取方式 性能 使用难度 安装难度
  正则表达式
  快的
  困难
  简单(内置模块)
  美丽的汤
  慢
  简单的
  简单(纯 Python)
  lxml
  快的
  简单的
  比较困难
  如果您的爬虫的瓶颈是下载页面,而不是提取数据,那么使用较慢的方法(如 Beautiful Soup)不是问题。正则表达式在一次提取中非常有用,除了避免解析整个网页的开销之外,如果你只需要抓取少量数据并想避免额外的依赖,那么正则表达式可能更适合. 但是,一般来说,lxml 是抓取数据的最佳选择,因为它不仅速度更快,功能更强大,而正则表达式和 Beautiful Soup 仅在某些特定场景下才有用。

jquery抓取网页内容(jquery抓取网页内容很简单,具体可以用session模拟登录网页)

网站优化优采云 发表了文章 • 0 个评论 • 105 次浏览 • 2022-04-02 16:04 • 来自相关话题

  jquery抓取网页内容(jquery抓取网页内容很简单,具体可以用session模拟登录网页)
  jquery抓取网页内容很简单,具体可以用session模拟登录网页,在浏览器里输入图片地址,这样就会跳转到电商网站,并且显示该图片,然后再用另一套代码把网页内容显示出来,下面是以网页源码为例。首先在userdata_loader中加入canvasimgdataimg-id:canvas-idimg_cookie:cookieusername:admin然后重定向到首页,看图中间红色框框。
  接下来在canvas中加入canvas的animation,设置好该animation长度(方便到时渲染),双击某个loader,就会从浏览器扩展中得到一个img对象。接下来在loader中加入ts代码。方法很简单,只需要将canvas放到loader中即可。接下来就是加载图片即可。就我目前所用的项目,图片加载速度大概在12ms左右,已经能满足要求。
  应该可以。jquerysetoncontainer的animation是最合适的。另外就是尽量少用requestanimationframe等惰性方法,尽量用throttle,不然每一帧获取网络动画都很耗时。
  用ajax去请求图片,然后保存到一个图片,用loader渲染,
  1.加载图片2.利用js,
  看看这个,反正我是这么做的,确保它会在页面中等待解析ie==0/10ie6/9/11ie11/12(mozilla/5.0(windowsnt10.0;win64;x64)applewebkit/537.36(khtml,likegecko)chrome/73.0.3686.0safari/537.36等待等待一段时间保存图片。等待有时间了再解析返回结果。 查看全部

  jquery抓取网页内容(jquery抓取网页内容很简单,具体可以用session模拟登录网页)
  jquery抓取网页内容很简单,具体可以用session模拟登录网页,在浏览器里输入图片地址,这样就会跳转到电商网站,并且显示该图片,然后再用另一套代码把网页内容显示出来,下面是以网页源码为例。首先在userdata_loader中加入canvasimgdataimg-id:canvas-idimg_cookie:cookieusername:admin然后重定向到首页,看图中间红色框框。
  接下来在canvas中加入canvas的animation,设置好该animation长度(方便到时渲染),双击某个loader,就会从浏览器扩展中得到一个img对象。接下来在loader中加入ts代码。方法很简单,只需要将canvas放到loader中即可。接下来就是加载图片即可。就我目前所用的项目,图片加载速度大概在12ms左右,已经能满足要求。
  应该可以。jquerysetoncontainer的animation是最合适的。另外就是尽量少用requestanimationframe等惰性方法,尽量用throttle,不然每一帧获取网络动画都很耗时。
  用ajax去请求图片,然后保存到一个图片,用loader渲染,
  1.加载图片2.利用js,
  看看这个,反正我是这么做的,确保它会在页面中等待解析ie==0/10ie6/9/11ie11/12(mozilla/5.0(windowsnt10.0;win64;x64)applewebkit/537.36(khtml,likegecko)chrome/73.0.3686.0safari/537.36等待等待一段时间保存图片。等待有时间了再解析返回结果。

jquery抓取网页内容(Excel教程Excel函数Excel表格制作Excel2010Excel实用技巧Excel视频教程)

网站优化优采云 发表了文章 • 0 个评论 • 53 次浏览 • 2022-03-31 12:02 • 来自相关话题

  jquery抓取网页内容(Excel教程Excel函数Excel表格制作Excel2010Excel实用技巧Excel视频教程)
  up=urllib2.urlopen(url)#打开目标页面并存入变量up
  cont=up.read()#从up读取HTML文件
  key1='key2="target"#设置关键字2
  pa=cont.find(key1)#查找关键字1的位置
  pt=cont.find(key2,pa)#查找关键字2的位置(从单词1的后面开始)
  urlx=cont[pa:pt]#获取关键字1和关键字2之间的内容(即想要的数据)
  打印网址
  但是在动态页面中,显示的内容往往不是通过HTML页面呈现,而是通过调用js等从数据库中获取数据,回显到网页中。以国家发改委网站上的“备案信息”( )为例,抓取该页面的部分备案项目。例如””。
  因此,在浏览器中打开此页面:
  相关信息显示的很全,但是如果按照前面的方法:
  复制代码代码如下:
  up=urllib2.urlopen(url)
  续=up.read()
  所谓动态页面也是通过Http请求实现的。动态页面的生成是基于不同用户输入的需求。使用python模拟用户的输入,填写相应的表单并发送请求和参数较多的一般静态请求传递
  Python爬取动态和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或IP限制。
  如果你要抓取的动态页面没有这些限制,可以使用和抓取静态页面一样的方法,比如如下:
  导入 urllib2url = "xxxxxx" 打印 urllib2.urlopen(url).read()
  如何使用Python爬取动态页面信息————Python爬取动态页面和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或ip限制。如果要捕获的动态页面没有这些限制,那么可以使用和静态页面一样的方法,比如: import urllib2 url = "xxxxxx" print urllib2.urlopen(url).read ()
  python如何抓取动态页面内容?- —— 1.了解网页抓取的逻辑流程请参考:【整理】关于抓取网页、分析网页内容、模拟登陆的逻辑/流程网站及注意事项&lt; @2.重用工具分析所需内容是如何生成的【总结】浏览器中的开发者工具(IE9的F12和Chrome的Ctrl+Shift+I)——网页分析的强大工具也可以用,不过我用过,感觉不如IE9的F12好用。3.已经分析过了,找出具体是哪个url生成了你需要的数据,然后用Python实现对应的代码。
  python3如何爬取动态加载的网页信息——方法一在页面中查找xhr请求,获取实际请求参数。直接获取相关搜索的请求返回码,然后进行数据排序。方法 2 模拟浏览器操作,例如使用 Selenium 模块。
  如何使用Python抓取动态页面信息——selenium webdriverFirefox()implicitly_wait(3)查看网页请求获取数据时一般会请求其他地址,也可以获取信息。你的问题太笼统了,所以这个是唯一的答案
  如何使用Python抓取动态页面信息—— 1、使用模拟浏览器 2、找到对应的ajax url,提交ajax请求,如果是js动态加载的,可以使用pyV8第三方包解析js
  如何使用Python捕获动态页面信息——先从本文中捕获动态页面数据的相关工具和库开始:1. python 2.7 2. pyqt 3.@ &gt; spynner(在安装过程中,其他一些依赖库也会自动下载在线安装) 4. BeautifulSoup 5. ide工具是pycharm(当然这只是个人喜好,其他ide工具也可用于)...
  如何使用Python捕获动态页面信息——1.自己分析ajax2.使用python控制webkit、无界面浏览器、或者selenuim技术直接获取解析加载的html
  如何使用Python抓取动态页面信息——这个要先研究动态页面中不变的部分,然后通过字符串处理提取出需要的信息
  如何使用Python抓取动态页面信息——很久以前,在学习Python网页编程的时候,涉及到一个Python urllib。您可以使用 urllib.urlopen("url").read() 轻松读取页面上的信息静态信息。但是随着时代的发展,越来越多的网页使用javascript、jQuery、PHP等语言来动态生成页面信息。所以...
  如何使用python爬取动态页面信息————python爬取动态页面和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或IP限制。如果你想捕获的动态页面没有这些限制,那么你可以使用和静态页面一样的方法,例如: import urllib2url = "xxxxxx" print urllib2.urlopen(url).read( ) 查看全部

  jquery抓取网页内容(Excel教程Excel函数Excel表格制作Excel2010Excel实用技巧Excel视频教程)
  up=urllib2.urlopen(url)#打开目标页面并存入变量up
  cont=up.read()#从up读取HTML文件
  key1='key2="target"#设置关键字2
  pa=cont.find(key1)#查找关键字1的位置
  pt=cont.find(key2,pa)#查找关键字2的位置(从单词1的后面开始)
  urlx=cont[pa:pt]#获取关键字1和关键字2之间的内容(即想要的数据)
  打印网址
  但是在动态页面中,显示的内容往往不是通过HTML页面呈现,而是通过调用js等从数据库中获取数据,回显到网页中。以国家发改委网站上的“备案信息”( )为例,抓取该页面的部分备案项目。例如””。
  因此,在浏览器中打开此页面:
  相关信息显示的很全,但是如果按照前面的方法:
  复制代码代码如下:
  up=urllib2.urlopen(url)
  续=up.read()
  所谓动态页面也是通过Http请求实现的。动态页面的生成是基于不同用户输入的需求。使用python模拟用户的输入,填写相应的表单并发送请求和参数较多的一般静态请求传递
  Python爬取动态和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或IP限制。
  如果你要抓取的动态页面没有这些限制,可以使用和抓取静态页面一样的方法,比如如下:
  导入 urllib2url = "xxxxxx" 打印 urllib2.urlopen(url).read()
  如何使用Python爬取动态页面信息————Python爬取动态页面和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或ip限制。如果要捕获的动态页面没有这些限制,那么可以使用和静态页面一样的方法,比如: import urllib2 url = "xxxxxx" print urllib2.urlopen(url).read ()
  python如何抓取动态页面内容?- —— 1.了解网页抓取的逻辑流程请参考:【整理】关于抓取网页、分析网页内容、模拟登陆的逻辑/流程网站及注意事项&lt; @2.重用工具分析所需内容是如何生成的【总结】浏览器中的开发者工具(IE9的F12和Chrome的Ctrl+Shift+I)——网页分析的强大工具也可以用,不过我用过,感觉不如IE9的F12好用。3.已经分析过了,找出具体是哪个url生成了你需要的数据,然后用Python实现对应的代码。
  python3如何爬取动态加载的网页信息——方法一在页面中查找xhr请求,获取实际请求参数。直接获取相关搜索的请求返回码,然后进行数据排序。方法 2 模拟浏览器操作,例如使用 Selenium 模块。
  如何使用Python抓取动态页面信息——selenium webdriverFirefox()implicitly_wait(3)查看网页请求获取数据时一般会请求其他地址,也可以获取信息。你的问题太笼统了,所以这个是唯一的答案
  如何使用Python抓取动态页面信息—— 1、使用模拟浏览器 2、找到对应的ajax url,提交ajax请求,如果是js动态加载的,可以使用pyV8第三方包解析js
  如何使用Python捕获动态页面信息——先从本文中捕获动态页面数据的相关工具和库开始:1. python 2.7 2. pyqt 3.@ &gt; spynner(在安装过程中,其他一些依赖库也会自动下载在线安装) 4. BeautifulSoup 5. ide工具是pycharm(当然这只是个人喜好,其他ide工具也可用于)...
  如何使用Python捕获动态页面信息——1.自己分析ajax2.使用python控制webkit、无界面浏览器、或者selenuim技术直接获取解析加载的html
  如何使用Python抓取动态页面信息——这个要先研究动态页面中不变的部分,然后通过字符串处理提取出需要的信息
  如何使用Python抓取动态页面信息——很久以前,在学习Python网页编程的时候,涉及到一个Python urllib。您可以使用 urllib.urlopen("url").read() 轻松读取页面上的信息静态信息。但是随着时代的发展,越来越多的网页使用javascript、jQuery、PHP等语言来动态生成页面信息。所以...
  如何使用python爬取动态页面信息————python爬取动态页面和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或IP限制。如果你想捕获的动态页面没有这些限制,那么你可以使用和静态页面一样的方法,例如: import urllib2url = "xxxxxx" print urllib2.urlopen(url).read( )

新手学爬虫的人多了去了我这本书

网站优化优采云 发表了文章 • 0 个评论 • 69 次浏览 • 2022-05-13 11:01 • 来自相关话题

  新手学爬虫的人多了去了我这本书
  jquery抓取网页内容(最好https),推荐看下这个,分享下我自己总结的一些爬虫基础知识。想学习爬虫的朋友,
  我是从《老子》这本书入门的,看了三天,几乎到了语文老师教学时都会做的题目和写的作文,然后然后就开始啃python爬虫了。发现挺多很基础的东西,挺适合新手学的,知识清晰,各种代码规范,js的劫持方法,的体验做的很好,这本书看了两遍,
  python三大范式那块去掉。python特色就是解释型。初学python的话,官方有大量教程,特别是第二版,可以当python基础教程。当你写了一大堆的爬虫程序后,你会明白自己到底不太明白python的特性。爬虫这个东西吧,就跟写小说,差不多。小说需要很多工具(用户设置、故事情节)。爬虫也一样,一般都是把已有的东西动态地找过来加以改造。
  不然你能不能写好东西完全取决于你的技术和你的生活环境。python的范式就是清晰不含糊。python从03版开始就有很多标准库,这几年python发展的非常好,包很多,这就是标准库的好处。基础很好的人去学这个语言很有优势。以上都是废话。想学爬虫的人多了去了,你来我这看看有没有人回答吧。祝好运。 查看全部

  新手学爬虫的人多了去了我这本书
  jquery抓取网页内容(最好https),推荐看下这个,分享下我自己总结的一些爬虫基础知识。想学习爬虫的朋友,
  我是从《老子》这本书入门的,看了三天,几乎到了语文老师教学时都会做的题目和写的作文,然后然后就开始啃python爬虫了。发现挺多很基础的东西,挺适合新手学的,知识清晰,各种代码规范,js的劫持方法,的体验做的很好,这本书看了两遍,
  python三大范式那块去掉。python特色就是解释型。初学python的话,官方有大量教程,特别是第二版,可以当python基础教程。当你写了一大堆的爬虫程序后,你会明白自己到底不太明白python的特性。爬虫这个东西吧,就跟写小说,差不多。小说需要很多工具(用户设置、故事情节)。爬虫也一样,一般都是把已有的东西动态地找过来加以改造。
  不然你能不能写好东西完全取决于你的技术和你的生活环境。python的范式就是清晰不含糊。python从03版开始就有很多标准库,这几年python发展的非常好,包很多,这就是标准库的好处。基础很好的人去学这个语言很有优势。以上都是废话。想学爬虫的人多了去了,你来我这看看有没有人回答吧。祝好运。

网络爬虫与网页自动化操作:最小化版系统学习的大纲

网站优化优采云 发表了文章 • 0 个评论 • 280 次浏览 • 2022-05-12 02:08 • 来自相关话题

  网络爬虫与网页自动化操作:最小化版系统学习的大纲
  
  我是DJun(小丁),码龄18年,从事IT工作5年,踩过无数“语言”坑最后入坑Python,想通过公众号,把自己的成长经历与经验分享给朋友们。
  同名酷安看看号“好想学Python”已开通,欢迎订阅。
  本篇摘要
  “网络爬虫”“网页自动化”听起来很神秘,其实入门并不会特别难。目前网络上关于Python爬虫的资料层出不穷。博文大多以具体应用内容为目标用简短代码实现基本功能,但缺乏大纲展现;网络视频教程或者书籍的覆盖较为全面,但缺乏灵活使用的经验总结。本篇介绍入门它们至少需要了解和学习的知识点,希望对需要的朋友有所帮助。
  往期精选
  >>>
  >>>
  >>>
  >>>
  >>>
  >>>
  >>>
  01
  什么是“网络爬虫”?什么是“网页自动化”?
  “网络爬虫”是一种在网络上获取公开数据的操作方式,是一种获取网络上数据的程序或者脚本。常见的,比如某电影网站的电影评分数据、评论信息分析,比如某商品在各大电商平台的价位走势对比,等等,这些数据分析所用数据来源大多是通过爬虫获取的。
  “网页自动化”是一种自动去操作网页浏览器实现某些测试目的的操作方式,是一种自动操作浏览器的程序或者脚本。常见的,比如Web开发者测试网站,比如抢车票、抢优惠券,等等。
  02
  为什么选用Python做它们的开发?
  爬虫的本质是进行HTTP请求、获取数据、解析数据,网页自动化的本质是对浏览器程序发送操作指令,而Python等程序语言只是一种工具,大多数语言都可以实现前面所述的操作。Python因其语言特性灵活、易用性高、扩展性强、跨平台,快速开发,从各方面来看都极适合做“网络爬虫”“网页自动化”的开发。
  03
  系统学习的最小化版大纲内容
  整体学习思路:数据存储结构——网页基础知识——程序开发应用
  
  01
  数据存储结构
  ① JSON/BSON
  JSON是JavaScript Object Notation的缩写,意为JS对象简谱,是一种轻量级的数据交换格式。由于其易于人阅读和编写,同时也易于机器解析和生成,并能有效地提升网络传输效率,不论是在解析爬虫数据上,还是在程序中保存本地数据上,都非常好用。
  BSON 缩写看起来很像JSON,它是Binary Serialized Document Format的缩写,意为二进制序列化式文档格式,是一种二进制存储格式,也可以做为网络数据交换的一种存储形式,具有轻量性、可遍历性、高效性的特点,常见于时常用于爬虫数据记录的MongoDB这种文档型数据库中,使用起来跟JSON并无太大差异。在MongoDB 数据库上可以以类似JSON的形式将文档数据写入数据库。
  在Python中,操作JSON的模块叫json,是自带模块;操作MongoDB的第三方模块叫pymongo,可以通过pip命令直接安装。
  ②CSV
  CSV是Comma-Separated Values的缩写,意为字符分隔值,是最常见的纯文本形式保存数据的格式。简单形容它的格式内容,通常是每行包含一个数据记录,同一行中用逗号对每列数据进行分隔,单行数据是像“1,Tom,male,18,student”这样的形式。
  大多数人对这种格式的数据有一些误解,一个是它能用Excel打开,所以误称之为“Excel表文件”;一个是它每列数据都用逗号间隔,但不了解它的引号有“转义”的作用,可以对逗号、引号本身作转义。
  通过改变“逗号”列分隔符、“引号”转义符、“回车”行分隔符的符号约定,可以产生各种变体,但实质都遵守类似CSV格式的规则。
  在Python中,操作CSV的模块叫csv,是自带模块。
  ③TEXT
  TEXT通常指纯文本数据,是最常见的文本数据格式,一般通过纯文本编辑器(比如记事本)直接打开即可阅读内容。
  但需要留意的是,文本数据通常有“字符编码”的问题,因为底层是用字节数据储存的,显示成什么样的文字是“字符编码”决定的,但具体到某个文件的字符编码是“GBK”还是“UTF-8”又是文件内容决定的;也需要留意的是,CSV的本质是纯文本文件,也会有同样的“字符编码”的问题,用Excel直接打开CSV文件是最糟糕的选择,通常在Windows中文系统下Excel打开CSV文件默认只解析GBK编码。推荐使用EmEditor、Notepad++打开这类文件。
  在Python中,操作TEXT通常通过直接的文件打开进行操作(open(),mode为'r'或'w')。
  ④XML
  XML是Extensible Markup Language的缩写,意为可扩展标记语言,是一种通用的用于标记电子文件使其具有结构性的标记语言。它也可以存储数据,可以作标签、标记属性,还可以展现层级关系。用于展示网页内容的HTML超文本标记语言可以看成是它的子集。
  在Python中,操作XML通常用第三方模块lxml进行操作,简单易用,可以通过pip命令直接安装。
  ⑤数据库
  数据库是按照数据结构来组织、存储和管理数据的仓库。分为关系型数据库(SQLite、MySQL、Oracle、PostgreSQL等),非关系型数据库(Redis、MongoDB、Neo4J等)。关系型数据库通过SQL语句操作数据,效率非常高;非关系型数据库由于优化了查找性能和存储结构,常用于内容缓存、分布式文件系统、Web应用等。
  SQLite是一款轻型关系型数据库,支持存储在单一文件中或内存中,而且Python自带SQLite的操作模块叫sqlite3,如果应用场景的要求并不高,用它很合适。
  关系型数据库推荐学习MySQL,目前属于Oracle旗下产品,开源、体积小、速度快,一般中小型网站的开发都会选择它作为网站数据库。
  非关系型数据库推荐学习MongoDB,由于采用BSON进行文档存储,在网络爬虫应用中非常好用。
  02
  网页基础知识
  ①HTML
  HTML是HyperText Markup Language的缩写,意为超文本标记语言。对HTML最直观的的感受是在我们浏览网页的时候,在页面上所见到的内容。
  爬虫的其中一种操作方式是,获取到HTML的源码数据,然后对其解析得到我们需要的数据内容。
  浏览器可以直接查看HTML源码,通过自带的“开发者工具”(一般是按F12呼出),既可以分析代码,也可以在其中的Console里执行调试JS代码。在这里分析得到数据所在路径后,就可以很轻松地编写代码进行爬取了。
  ②JavaScript
  JS,即JavaScript,是一种直译式脚本语言,可以用于给HTML网页增加动态功能。JavaScript引擎现已经成为浏览器的一部分。
  在爬虫应用中,JS通常用于改变网页内容(比如去水印),或者获取以JS之外的方式难获取的网页内容,等;在网页自动化应用中,JS通常用于高级操作(比如下拉刷新),或者直接调用JS函数得到所需数据,等。
  ③XPath/CSS Selector
  XPath是XML路径的意思,它是一种用来确定XML文档中某部分位置的强大语言。
  CSS Selector是CSS选择器的意思,它是一种与XPath不同语法,但作用相似、功能同样强大的语言,一般用于CSS上。
  通过XPath、CSSSelector这两件利器,总结具体网页的HTML元素排列规律,可以精准定位到我们所需要的数据的相关元素上,在某种程度上比以面向对象方式定位网页元素的操作(通常以BeautifulSoup作为代表)更为便捷。
  第三方模块lxml支持XPath定位元素的操作;第三方模块PyQuery模仿jQuery方式处理HTML,可以使用与jQuery同款的CSSSelector定位元素;第三方模块selenium同时支持XPath和CSS Selector定位元素的操作。
  03
  程序开发应用
  ①Python模块:lxml +json + re +requests +selenium
  在爬虫应用中,requests、selenium担当获取数据的角色,lxml、json、re担当解析数据的角色。requests适用于不需要JavaScript渲染就可以获取得到的网页数据或者API返回结果数据(比如百度搜索结果,天气JSON API)的情景,selenium适用于需要JavaScript渲染的情景(比如微博,空间,下拉刷新)。从requests或selenium获取到content或者page_source之后,根据数据类型进行处理,如果是json类型就用json模块解析,如果是HTML源码则用lxml解析。
  在网页自动化应用中,selenium担当向浏览器发送控制指令的控制者角色,只要把需要做的自动操作通过程序代码直接实现即可。
  笔者并不是很推荐用第三方模块BeautifulSoup进行HTML解析,在大多数情况下,它没有XPath那么简洁有力。
  正则表达式解析(Python自带的re模块)在某些情况下甚是好用,但笔者建议,目前大多数解析数据的方式都可以通过HTML解析得到,较少出现需要正则表达式解析的情况,正则表达式的编写和维护相对XPath等较难,可以不用正则的时候尽量不要使用。
  可能听说过像Scrapy这样的强大的爬虫框架,笔者建议初入门的朋友先跳过Scrapy,先掌握上述几个最常用的模块,之后再接触它。
  ②抓包工具:Fiddler
  Fiddler官方地址:
  通过Fiddler可以很方便地在访问网站的过程中进行抓包操作,其中一种应用情景是,找出在网页显示我们所要抓取的内容的背后可能进行的后台数据请求操作,然后配合requests模块直接把需要的数据一举抓取下来。
  ③面向对象:类(class)
  网络博文在讲解具体爬虫应用时,往往为了简略实现,不会以面向对象的思维来写爬虫。优秀的项目代码例子较为少见。
  在先前笔者的文章《面向你的对象,写一手漂亮的类》()中提到,面向对象可以“帮助我们更好地组织程序代码,在提高效率的同时,在程序内部实现高内聚、低耦合,后期维护也很方便”。而“网络爬虫”“网页自动化”的应用要形成一个大的项目规模的时候,必须在一开始的时候就以面向对象的思维进行思考,构建整个项目的框架,再逐步开发。
  一个完整的“网络爬虫”项目,通常会包括获取数据、解析数据、保存数据等这几部分;而一个完整的“网页自动化”项目,通常会包括实施者的配置、实施操作步骤、记录操作结果等这几部分。编写代码时,可以分别对每个部分进行包装,并且把具体数据(比如网址URL、抓取规则、操作步骤数据)从代码中分离出来,从外部读入,程序代码内只实现固定不变的那几部分。
  在做爬虫程序练习时,通常是以一个具体的实现目标来做的,我们可以就着这样的练习机会,把它们分别都当做是一个个的小项目对待,多参考相关资料,用面向对象的思维边学边做,从一个小的项目里把类包装完整,再拷贝到新的小项目中把它们复用起来。这样不仅能提升代码能力,而且积累出来的代码复用性会随着每一次的迁移、改进不断地提高,可以很大程度节省学习时间和开发新程序的成本。
  
  希望本篇可以给感兴趣或者想要学习的朋友们带来帮助哈。
  有其他疑问也请在下方留言提出,会尽力解答~ 查看全部

  网络爬虫与网页自动化操作:最小化版系统学习的大纲
  
  我是DJun(小丁),码龄18年,从事IT工作5年,踩过无数“语言”坑最后入坑Python,想通过公众号,把自己的成长经历与经验分享给朋友们。
  同名酷安看看号“好想学Python”已开通,欢迎订阅。
  本篇摘要
  “网络爬虫”“网页自动化”听起来很神秘,其实入门并不会特别难。目前网络上关于Python爬虫的资料层出不穷。博文大多以具体应用内容为目标用简短代码实现基本功能,但缺乏大纲展现;网络视频教程或者书籍的覆盖较为全面,但缺乏灵活使用的经验总结。本篇介绍入门它们至少需要了解和学习的知识点,希望对需要的朋友有所帮助。
  往期精选
  >>>
  >>>
  >>>
  >>>
  >>>
  >>>
  >>>
  01
  什么是“网络爬虫”?什么是“网页自动化”?
  “网络爬虫”是一种在网络上获取公开数据的操作方式,是一种获取网络上数据的程序或者脚本。常见的,比如某电影网站的电影评分数据、评论信息分析,比如某商品在各大电商平台的价位走势对比,等等,这些数据分析所用数据来源大多是通过爬虫获取的。
  “网页自动化”是一种自动去操作网页浏览器实现某些测试目的的操作方式,是一种自动操作浏览器的程序或者脚本。常见的,比如Web开发者测试网站,比如抢车票、抢优惠券,等等。
  02
  为什么选用Python做它们的开发?
  爬虫的本质是进行HTTP请求、获取数据、解析数据,网页自动化的本质是对浏览器程序发送操作指令,而Python等程序语言只是一种工具,大多数语言都可以实现前面所述的操作。Python因其语言特性灵活、易用性高、扩展性强、跨平台,快速开发,从各方面来看都极适合做“网络爬虫”“网页自动化”的开发。
  03
  系统学习的最小化版大纲内容
  整体学习思路:数据存储结构——网页基础知识——程序开发应用
  
  01
  数据存储结构
  ① JSON/BSON
  JSON是JavaScript Object Notation的缩写,意为JS对象简谱,是一种轻量级的数据交换格式。由于其易于人阅读和编写,同时也易于机器解析和生成,并能有效地提升网络传输效率,不论是在解析爬虫数据上,还是在程序中保存本地数据上,都非常好用。
  BSON 缩写看起来很像JSON,它是Binary Serialized Document Format的缩写,意为二进制序列化式文档格式,是一种二进制存储格式,也可以做为网络数据交换的一种存储形式,具有轻量性、可遍历性、高效性的特点,常见于时常用于爬虫数据记录的MongoDB这种文档型数据库中,使用起来跟JSON并无太大差异。在MongoDB 数据库上可以以类似JSON的形式将文档数据写入数据库。
  在Python中,操作JSON的模块叫json,是自带模块;操作MongoDB的第三方模块叫pymongo,可以通过pip命令直接安装。
  ②CSV
  CSV是Comma-Separated Values的缩写,意为字符分隔值,是最常见的纯文本形式保存数据的格式。简单形容它的格式内容,通常是每行包含一个数据记录,同一行中用逗号对每列数据进行分隔,单行数据是像“1,Tom,male,18,student”这样的形式。
  大多数人对这种格式的数据有一些误解,一个是它能用Excel打开,所以误称之为“Excel表文件”;一个是它每列数据都用逗号间隔,但不了解它的引号有“转义”的作用,可以对逗号、引号本身作转义。
  通过改变“逗号”列分隔符、“引号”转义符、“回车”行分隔符的符号约定,可以产生各种变体,但实质都遵守类似CSV格式的规则。
  在Python中,操作CSV的模块叫csv,是自带模块。
  ③TEXT
  TEXT通常指纯文本数据,是最常见的文本数据格式,一般通过纯文本编辑器(比如记事本)直接打开即可阅读内容。
  但需要留意的是,文本数据通常有“字符编码”的问题,因为底层是用字节数据储存的,显示成什么样的文字是“字符编码”决定的,但具体到某个文件的字符编码是“GBK”还是“UTF-8”又是文件内容决定的;也需要留意的是,CSV的本质是纯文本文件,也会有同样的“字符编码”的问题,用Excel直接打开CSV文件是最糟糕的选择,通常在Windows中文系统下Excel打开CSV文件默认只解析GBK编码。推荐使用EmEditor、Notepad++打开这类文件。
  在Python中,操作TEXT通常通过直接的文件打开进行操作(open(),mode为'r'或'w')。
  ④XML
  XML是Extensible Markup Language的缩写,意为可扩展标记语言,是一种通用的用于标记电子文件使其具有结构性的标记语言。它也可以存储数据,可以作标签、标记属性,还可以展现层级关系。用于展示网页内容的HTML超文本标记语言可以看成是它的子集。
  在Python中,操作XML通常用第三方模块lxml进行操作,简单易用,可以通过pip命令直接安装。
  ⑤数据库
  数据库是按照数据结构来组织、存储和管理数据的仓库。分为关系型数据库(SQLite、MySQL、Oracle、PostgreSQL等),非关系型数据库(Redis、MongoDB、Neo4J等)。关系型数据库通过SQL语句操作数据,效率非常高;非关系型数据库由于优化了查找性能和存储结构,常用于内容缓存、分布式文件系统、Web应用等。
  SQLite是一款轻型关系型数据库,支持存储在单一文件中或内存中,而且Python自带SQLite的操作模块叫sqlite3,如果应用场景的要求并不高,用它很合适。
  关系型数据库推荐学习MySQL,目前属于Oracle旗下产品,开源、体积小、速度快,一般中小型网站的开发都会选择它作为网站数据库。
  非关系型数据库推荐学习MongoDB,由于采用BSON进行文档存储,在网络爬虫应用中非常好用。
  02
  网页基础知识
  ①HTML
  HTML是HyperText Markup Language的缩写,意为超文本标记语言。对HTML最直观的的感受是在我们浏览网页的时候,在页面上所见到的内容。
  爬虫的其中一种操作方式是,获取到HTML的源码数据,然后对其解析得到我们需要的数据内容。
  浏览器可以直接查看HTML源码,通过自带的“开发者工具”(一般是按F12呼出),既可以分析代码,也可以在其中的Console里执行调试JS代码。在这里分析得到数据所在路径后,就可以很轻松地编写代码进行爬取了。
  ②JavaScript
  JS,即JavaScript,是一种直译式脚本语言,可以用于给HTML网页增加动态功能。JavaScript引擎现已经成为浏览器的一部分。
  在爬虫应用中,JS通常用于改变网页内容(比如去水印),或者获取以JS之外的方式难获取的网页内容,等;在网页自动化应用中,JS通常用于高级操作(比如下拉刷新),或者直接调用JS函数得到所需数据,等。
  ③XPath/CSS Selector
  XPath是XML路径的意思,它是一种用来确定XML文档中某部分位置的强大语言。
  CSS Selector是CSS选择器的意思,它是一种与XPath不同语法,但作用相似、功能同样强大的语言,一般用于CSS上。
  通过XPath、CSSSelector这两件利器,总结具体网页的HTML元素排列规律,可以精准定位到我们所需要的数据的相关元素上,在某种程度上比以面向对象方式定位网页元素的操作(通常以BeautifulSoup作为代表)更为便捷。
  第三方模块lxml支持XPath定位元素的操作;第三方模块PyQuery模仿jQuery方式处理HTML,可以使用与jQuery同款的CSSSelector定位元素;第三方模块selenium同时支持XPath和CSS Selector定位元素的操作。
  03
  程序开发应用
  ①Python模块:lxml +json + re +requests +selenium
  在爬虫应用中,requests、selenium担当获取数据的角色,lxml、json、re担当解析数据的角色。requests适用于不需要JavaScript渲染就可以获取得到的网页数据或者API返回结果数据(比如百度搜索结果,天气JSON API)的情景,selenium适用于需要JavaScript渲染的情景(比如微博,空间,下拉刷新)。从requests或selenium获取到content或者page_source之后,根据数据类型进行处理,如果是json类型就用json模块解析,如果是HTML源码则用lxml解析。
  在网页自动化应用中,selenium担当向浏览器发送控制指令的控制者角色,只要把需要做的自动操作通过程序代码直接实现即可。
  笔者并不是很推荐用第三方模块BeautifulSoup进行HTML解析,在大多数情况下,它没有XPath那么简洁有力。
  正则表达式解析(Python自带的re模块)在某些情况下甚是好用,但笔者建议,目前大多数解析数据的方式都可以通过HTML解析得到,较少出现需要正则表达式解析的情况,正则表达式的编写和维护相对XPath等较难,可以不用正则的时候尽量不要使用。
  可能听说过像Scrapy这样的强大的爬虫框架,笔者建议初入门的朋友先跳过Scrapy,先掌握上述几个最常用的模块,之后再接触它。
  ②抓包工具:Fiddler
  Fiddler官方地址:
  通过Fiddler可以很方便地在访问网站的过程中进行抓包操作,其中一种应用情景是,找出在网页显示我们所要抓取的内容的背后可能进行的后台数据请求操作,然后配合requests模块直接把需要的数据一举抓取下来。
  ③面向对象:类(class)
  网络博文在讲解具体爬虫应用时,往往为了简略实现,不会以面向对象的思维来写爬虫。优秀的项目代码例子较为少见。
  在先前笔者的文章《面向你的对象,写一手漂亮的类》()中提到,面向对象可以“帮助我们更好地组织程序代码,在提高效率的同时,在程序内部实现高内聚、低耦合,后期维护也很方便”。而“网络爬虫”“网页自动化”的应用要形成一个大的项目规模的时候,必须在一开始的时候就以面向对象的思维进行思考,构建整个项目的框架,再逐步开发。
  一个完整的“网络爬虫”项目,通常会包括获取数据、解析数据、保存数据等这几部分;而一个完整的“网页自动化”项目,通常会包括实施者的配置、实施操作步骤、记录操作结果等这几部分。编写代码时,可以分别对每个部分进行包装,并且把具体数据(比如网址URL、抓取规则、操作步骤数据)从代码中分离出来,从外部读入,程序代码内只实现固定不变的那几部分。
  在做爬虫程序练习时,通常是以一个具体的实现目标来做的,我们可以就着这样的练习机会,把它们分别都当做是一个个的小项目对待,多参考相关资料,用面向对象的思维边学边做,从一个小的项目里把类包装完整,再拷贝到新的小项目中把它们复用起来。这样不仅能提升代码能力,而且积累出来的代码复用性会随着每一次的迁移、改进不断地提高,可以很大程度节省学习时间和开发新程序的成本。
  
  希望本篇可以给感兴趣或者想要学习的朋友们带来帮助哈。
  有其他疑问也请在下方留言提出,会尽力解答~

【编程课堂】以 jQuery 之名 - 爬虫利器 PyQuery

网站优化优采云 发表了文章 • 0 个评论 • 76 次浏览 • 2022-05-09 13:36 • 来自相关话题

  【编程课堂】以 jQuery 之名 - 爬虫利器 PyQuery
  
  根据 id 定位找到这个li标签,代码如下:
  # 定位 id = note-11772642 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />pq_id = pq('#note-11772642')
  以上代码获取id名为note-11772642的标签,需要注意的是查询 id 时添加#前缀,这是 css 选择器语法。
  根据 class 定位:
  同样以刚才的为例
  
  我们根据class=have-img去获取这个li标签
  # 定位 class = have-img 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />pq_class = pq('.have-img')
  注意的是查询class时添加.前缀,这也是 css 选择器语法。
  2.3 索引标签
  在上一节的最后有个小问题,我们知道head标签在 html 中只有一个,而class名为have-img的li标签可能有多个,我们该
  如何遍历所有的li标签呢? 又该如何单独的取某一个li呢?
  首先我们可以逐个遍历
  # 遍历所有 class = have-img 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />for li in pq_class:    <br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />    # 获取每一个 li 标签
   pq_li = pq(li)
  我们可以索引某一个li标签
  使用.ep(index)函数。
  # 获取第一个 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_first = pq_class.ep(0)<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" /># 获取第二个 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_second = pq_class.ep(1)
  2.4 寻找标签
  同样回到刚刚的那张图
  
  在上一步,我们已经找到了所有的li标签,也知道如何取索引其中的元素,但我们现在要准确定位到某一个元素,比如上图中id = note-11772642这个li标签。
  这时候filter(selecter)就派上了用场
  li_spec = pq_class.filter('#note-11772642')
  这样我们就找到了指定的这个li标签,需要注意的是,filter函数只能在同一级标签中寻找,比如在这里只能过滤li标签,而不能定位li标签下的a标签、div标签等。
  当然,针对这种情况, pyquery 为我们提供了另外一个函数find(selector),该函数用于寻找子节点,继续以上图为例,寻找该特定 li 标签下的 p 标签
  p_tag = li_spec.find('p')
  2.5 提取属性与值
  以上我们讲了许多关于标签的知识,现在来谈谈怎么获取标签内的属性和标签包裹的文本,实际的爬虫项目中,通常这是最重要的一步,比如从a标签中获取链接、从li标签或者p标签中获取文本。
  获取属性:
  使用attr()函数,以我们之前获取的li标签为例,获取其中的id属性
  # 获取 id 属性的方法<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_spec_id = li_spec.attr('id')
li_spec_id_2 = li_spec.attr.id
li_spec_id_3 = li_spec.attr['id']
  获取文本:
  使用text()函数, 以我们之前得到的p标签为例,获取其中的文本。
  string = p_tag.text()
  到此,在爬虫中会使用到的函数就是这些了。
  3、小结
  pyquery 还拥有操作文档树的能力,本篇文章着重介绍与爬虫相关的知识,所以就不再此详细叙述了,有兴趣的同学移步官方文档:
  最后,既然我们都分析了简书首页,请大家根据所学内容爬取简书首页所有的文章标题和文章链接,然后打印出来吧,像下图一样
  
  在公众号(Crossin的编程教室)里回复 pyquery,可获取本文的完整示例代码。
  『码上行动』在线学习班正在开放中,详情回复码上行动 查看全部

  【编程课堂】以 jQuery 之名 - 爬虫利器 PyQuery
  
  根据 id 定位找到这个li标签,代码如下:
  # 定位 id = note-11772642 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />pq_id = pq('#note-11772642')
  以上代码获取id名为note-11772642的标签,需要注意的是查询 id 时添加#前缀,这是 css 选择器语法。
  根据 class 定位:
  同样以刚才的为例
  
  我们根据class=have-img去获取这个li标签
  # 定位 class = have-img 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />pq_class = pq('.have-img')
  注意的是查询class时添加.前缀,这也是 css 选择器语法。
  2.3 索引标签
  在上一节的最后有个小问题,我们知道head标签在 html 中只有一个,而class名为have-img的li标签可能有多个,我们该
  如何遍历所有的li标签呢? 又该如何单独的取某一个li呢?
  首先我们可以逐个遍历
  # 遍历所有 class = have-img 的 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />for li in pq_class:    <br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />    # 获取每一个 li 标签
   pq_li = pq(li)
  我们可以索引某一个li标签
  使用.ep(index)函数。
  # 获取第一个 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_first = pq_class.ep(0)<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" /># 获取第二个 li 标签<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_second = pq_class.ep(1)
  2.4 寻找标签
  同样回到刚刚的那张图
  
  在上一步,我们已经找到了所有的li标签,也知道如何取索引其中的元素,但我们现在要准确定位到某一个元素,比如上图中id = note-11772642这个li标签。
  这时候filter(selecter)就派上了用场
  li_spec = pq_class.filter('#note-11772642')
  这样我们就找到了指定的这个li标签,需要注意的是,filter函数只能在同一级标签中寻找,比如在这里只能过滤li标签,而不能定位li标签下的a标签、div标签等。
  当然,针对这种情况, pyquery 为我们提供了另外一个函数find(selector),该函数用于寻找子节点,继续以上图为例,寻找该特定 li 标签下的 p 标签
  p_tag = li_spec.find('p')
  2.5 提取属性与值
  以上我们讲了许多关于标签的知识,现在来谈谈怎么获取标签内的属性和标签包裹的文本,实际的爬虫项目中,通常这是最重要的一步,比如从a标签中获取链接、从li标签或者p标签中获取文本。
  获取属性:
  使用attr()函数,以我们之前获取的li标签为例,获取其中的id属性
  # 获取 id 属性的方法<br style="max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;" />li_spec_id = li_spec.attr('id')
li_spec_id_2 = li_spec.attr.id
li_spec_id_3 = li_spec.attr['id']
  获取文本:
  使用text()函数, 以我们之前得到的p标签为例,获取其中的文本。
  string = p_tag.text()
  到此,在爬虫中会使用到的函数就是这些了。
  3、小结
  pyquery 还拥有操作文档树的能力,本篇文章着重介绍与爬虫相关的知识,所以就不再此详细叙述了,有兴趣的同学移步官方文档:
  最后,既然我们都分析了简书首页,请大家根据所学内容爬取简书首页所有的文章标题和文章链接,然后打印出来吧,像下图一样
  
  在公众号(Crossin的编程教室)里回复 pyquery,可获取本文的完整示例代码。
  『码上行动』在线学习班正在开放中,详情回复码上行动

Taro + 小程序云开发实战|日语用例助手

网站优化优采云 发表了文章 • 0 个评论 • 110 次浏览 • 2022-05-05 15:05 • 来自相关话题

  Taro + 小程序云开发实战|日语用例助手
  前言
  小程序开放了云开发能力,为开发者提供了一个可以很快速构建小程序后端服务的能力,作为一名对新技术不倒腾不快的前端,对此也是很感兴趣的。
  Taro 是凹凸实验室推出的,基于React 语法规范的多端开发解决方案,较之于mpvue或者wepy,由于年轻,坑还比较多,但是很适合我这种倾向用React 开发的人。
  我结合这两者,使用cheerio和superagent 抓取了用例.jp, 开发了一个《日语用例助手》。
  入门踩坑1.云开发篇1.1 环境搭建
  云开发可以通过下列两种方式创建:1.使用quickstart(云开发快速启动模版)创建项目:
  
  这种方式会在目录下同时创建名为miniprogram ,带有云开发调用范例的小程序基础模板和名为cloudfuntions 的存放云函数的目录, 由此即可开始全新的项目。
  2.基于现有的小程序使用云开发:
  <p>在小程序目录下创建一个文件夹作为你的云函数目录,然后在project.config.json 文件中新增字段"cloudfunctionRoot": "你的云函数目录",即可以在微信开发者工具中看到目录的图标变成了云,在此目录下创建云函数即可;</p>
  
  1.2 云函数编写
  使用微信开发者工具在云函数目录下创建一个云函数时,会根据名称创建一个目录,目录中包含一个index.js 和package.json。
  在小程序中使用如下方式调用云函数:
  <p>wx.cloud.callFunction({
   name: '云函数名称',
   data: {
   key1: 'value1',
   key2: 'value2'
   }
  }).then((res) => {
   console.log(res);
  }).catch((e) => {
   console.log(e);
  });</p>
  index.js的入口函数如下所示:
  <p>//云函数入口函数
  exports.main = async (event, context) => {
   // 参数获取在event 中获取,如使用上面的调用函数后,获取data使用 event.key1、event.key2即可
   const { key1, key2 } = event;
   return { query: { key1, key2 } }
  }</p>
  每个云函数可视为一个单独的服务,如果需要安装第三方依赖,只需要在该目录点击右键,选择 在终端中打开, 并 npm install依赖即可。
  需要注意的是,每个云函数都是独立的,所需要的依赖都需要在对应的目录下进行 npm install,但这样就会使得项目变得十分庞大且不优雅。因此,接下来我介绍一下tcb-router。
  1.3 使用tcb-router管理路由
  tcb-router 是腾讯云团队开发的,基于 koa 风格的小程序·云开发云函数轻量级类路由库,主要用于优化服务端函数处理逻辑。
  使用tcb-router的方法很简单:
  <p>const TcbRouter = require('tcb-router');
  exports.main = (event, context) => {
   const app = new TcbRouter({ event });
   app.router('路由名称', async (ctx) => {
   //原有的event需要通过ctx._req.event 获取
   const { param1, param2 } = ctx._req.event;
   ctx.body = { key1: value1 };
   });
  })</p>
  此时小程序的调用方式也需要改成:
  <p>wx.cloud.callFunction({
   name: '云函数名称',
   data: {
   $url: '路由名称',
   // 其他数据
   param1: 'test1',
   param2: 'test2'
   },
   success: res => {},
   fail: err => {
   console.error(`[云函数] [${action}] 调用失败`, err)
   }
  })</p>
  2.Taro篇2.1 环境搭建
  <p>npm install -g @tarojs/cli
  taro init myApp</p>
  2.2 遇到的坑1.API支持不足
  由于Taro 对微信的一些新api 并没有支持到,比如使用云开发时需要用到 wx.cloud,Taro 并没有支持,但亲测是可以直接使用 wx 变量,但是会被eslint 提醒,看着十分不悦,可以在 .eslintrc 文件中增加以下代码:
  2.不能使用 Array#map 之外的方法操作 JSX 数组。
  3.不允许在 JSX 参数(props)中传入 JSX 元素(taro/no-jsx-in-props)。
  3.爬虫篇3.1 superagent
  superagent 是一个非常实用的http请求模块,用来抓取网页十分有用,使用也十分简单,以下是我在抓取 yourei.jp 时使用的代码:
  <p>// const superagent = require('superagent');
  // ...
  function crawler(url, cb) {
   return new Promise((resolve, reject) => {
   superagent.get(url).set({
   'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
   }).end(function (err, res) {
   if (err) {
   reject(err);
   return;
   }
   resolve(res);
   });
   });
  }</p>
  3.2 cheerio
  cheerio 是一个轻型灵活,类jQuery的对HTML元素分析操作的工具。在进行一些server端渲染的页面以及一些简单的小页面的爬取时,cheerio十分好用且高效。
  在使用 superagent 抓取了网页内容后,可以使用如下方式解析页面代码:
  <p> // const cheerio = require('cheerio');
   // ...
   const result = crawler(apiUrl).then((res) => {
   // 使用load 之后,$ 即可同jquery 一样使用选择器来选择元素了
   const $ = cheerio.load(res.text);
   const categories = [];
   $('[data-toggle]').each((i, ele) => {
   // 可以使用.text()、.html() 等方式获取元素的内容
   categories.push($(ele).attr('href'));
   });
   return {
   list: categories,
   };
   });</p>
  总结1.Taro
  如果你是React 开发者,需要开发多端小程序,或者原有React 项目想迁移到小程序,Taro 是个不错的选择,但还有很多坑没有填好,希望它的发展越来越好。
  2.云开发
  如果你是个人开发者,想尝试小程序开发又不想或者难以自己搭建服务器,云开发是个好选择,容易上手且十分敏捷。 查看全部

  Taro + 小程序云开发实战|日语用例助手
  前言
  小程序开放了云开发能力,为开发者提供了一个可以很快速构建小程序后端服务的能力,作为一名对新技术不倒腾不快的前端,对此也是很感兴趣的。
  Taro 是凹凸实验室推出的,基于React 语法规范的多端开发解决方案,较之于mpvue或者wepy,由于年轻,坑还比较多,但是很适合我这种倾向用React 开发的人。
  我结合这两者,使用cheerio和superagent 抓取了用例.jp, 开发了一个《日语用例助手》。
  入门踩坑1.云开发篇1.1 环境搭建
  云开发可以通过下列两种方式创建:1.使用quickstart(云开发快速启动模版)创建项目:
  
  这种方式会在目录下同时创建名为miniprogram ,带有云开发调用范例的小程序基础模板和名为cloudfuntions 的存放云函数的目录, 由此即可开始全新的项目。
  2.基于现有的小程序使用云开发:
  <p>在小程序目录下创建一个文件夹作为你的云函数目录,然后在project.config.json 文件中新增字段"cloudfunctionRoot": "你的云函数目录",即可以在微信开发者工具中看到目录的图标变成了云,在此目录下创建云函数即可;</p>
  
  1.2 云函数编写
  使用微信开发者工具在云函数目录下创建一个云函数时,会根据名称创建一个目录,目录中包含一个index.js 和package.json。
  在小程序中使用如下方式调用云函数:
  <p>wx.cloud.callFunction({
   name: '云函数名称',
   data: {
   key1: 'value1',
   key2: 'value2'
   }
  }).then((res) => {
   console.log(res);
  }).catch((e) => {
   console.log(e);
  });</p>
  index.js的入口函数如下所示:
  <p>//云函数入口函数
  exports.main = async (event, context) => {
   // 参数获取在event 中获取,如使用上面的调用函数后,获取data使用 event.key1、event.key2即可
   const { key1, key2 } = event;
   return { query: { key1, key2 } }
  }</p>
  每个云函数可视为一个单独的服务,如果需要安装第三方依赖,只需要在该目录点击右键,选择 在终端中打开, 并 npm install依赖即可。
  需要注意的是,每个云函数都是独立的,所需要的依赖都需要在对应的目录下进行 npm install,但这样就会使得项目变得十分庞大且不优雅。因此,接下来我介绍一下tcb-router。
  1.3 使用tcb-router管理路由
  tcb-router 是腾讯云团队开发的,基于 koa 风格的小程序·云开发云函数轻量级类路由库,主要用于优化服务端函数处理逻辑。
  使用tcb-router的方法很简单:
  <p>const TcbRouter = require('tcb-router');
  exports.main = (event, context) => {
   const app = new TcbRouter({ event });
   app.router('路由名称', async (ctx) => {
   //原有的event需要通过ctx._req.event 获取
   const { param1, param2 } = ctx._req.event;
   ctx.body = { key1: value1 };
   });
  })</p>
  此时小程序的调用方式也需要改成:
  <p>wx.cloud.callFunction({
   name: '云函数名称',
   data: {
   $url: '路由名称',
   // 其他数据
   param1: 'test1',
   param2: 'test2'
   },
   success: res => {},
   fail: err => {
   console.error(`[云函数] [${action}] 调用失败`, err)
   }
  })</p>
  2.Taro篇2.1 环境搭建
  <p>npm install -g @tarojs/cli
  taro init myApp</p>
  2.2 遇到的坑1.API支持不足
  由于Taro 对微信的一些新api 并没有支持到,比如使用云开发时需要用到 wx.cloud,Taro 并没有支持,但亲测是可以直接使用 wx 变量,但是会被eslint 提醒,看着十分不悦,可以在 .eslintrc 文件中增加以下代码:
  2.不能使用 Array#map 之外的方法操作 JSX 数组。
  3.不允许在 JSX 参数(props)中传入 JSX 元素(taro/no-jsx-in-props)。
  3.爬虫篇3.1 superagent
  superagent 是一个非常实用的http请求模块,用来抓取网页十分有用,使用也十分简单,以下是我在抓取 yourei.jp 时使用的代码:
  <p>// const superagent = require('superagent');
  // ...
  function crawler(url, cb) {
   return new Promise((resolve, reject) => {
   superagent.get(url).set({
   'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
   }).end(function (err, res) {
   if (err) {
   reject(err);
   return;
   }
   resolve(res);
   });
   });
  }</p>
  3.2 cheerio
  cheerio 是一个轻型灵活,类jQuery的对HTML元素分析操作的工具。在进行一些server端渲染的页面以及一些简单的小页面的爬取时,cheerio十分好用且高效。
  在使用 superagent 抓取了网页内容后,可以使用如下方式解析页面代码:
  <p> // const cheerio = require('cheerio');
   // ...
   const result = crawler(apiUrl).then((res) => {
   // 使用load 之后,$ 即可同jquery 一样使用选择器来选择元素了
   const $ = cheerio.load(res.text);
   const categories = [];
   $('[data-toggle]').each((i, ele) => {
   // 可以使用.text()、.html() 等方式获取元素的内容
   categories.push($(ele).attr('href'));
   });
   return {
   list: categories,
   };
   });</p>
  总结1.Taro
  如果你是React 开发者,需要开发多端小程序,或者原有React 项目想迁移到小程序,Taro 是个不错的选择,但还有很多坑没有填好,希望它的发展越来越好。
  2.云开发
  如果你是个人开发者,想尝试小程序开发又不想或者难以自己搭建服务器,云开发是个好选择,容易上手且十分敏捷。

Java做爬虫也很牛

网站优化优采云 发表了文章 • 0 个评论 • 98 次浏览 • 2022-05-05 15:00 • 来自相关话题

  Java做爬虫也很牛
  工具类实现比较简单,就一个get方法,读取请求地址的响应内容,这边我们用来抓取网页的内容,这边没有用代理,在真正的抓取过程中,当你大量请求某个网站的时候,对方会有一系列的策略来禁用你的请求,这个时候代理就排上用场了,通过代理设置不同的IP来抓取数据。
  import java.io.BufferedReader;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.io.InputStreamReader;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.net.HttpURLConnection;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.net.URL;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />public class HttpUtils {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static String get(String url) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        try {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            URL getUrl = new URL(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            HttpURLConnection connection = (HttpURLConnection) getUrl<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    .openConnection();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestMethod("GET");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestProperty("Accept", "*/*");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    .setRequestProperty("User-Agent",<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA)");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestProperty("Accept-Language", "zh-cn");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.connect();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            String line;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            StringBuffer result = new StringBuffer();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            while ((line = reader.readLine()) != null){<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                result.append(line);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            reader.close();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            return result.toString();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        } catch (Exception e) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            e.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        return null;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  接下来我们随便找一个有图片的网页,来试试抓取功能
  public static void main(String[] args) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List imgUrls = getImageSrc(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (String imgSrc : imgUrls) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            System.out.println(imgSrc);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static List getImageSrc(String html) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        // 获取img标签正则<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String IMGURL_REG = "]*?>";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        // 获取src路径的正则<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String IMGSRC_REG = "http:\"?(.*?)(\"|>|\\s+)";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Matcher matcher = Pattern.compile(IMGURL_REG).matcher(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List listImgUrl = new ArrayList();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        while (matcher.find()) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Matcher m = Pattern.compile(IMGSRC_REG).matcher(matcher.group());<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            while (m.find()) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                listImgUrl.add(m.group().substring(0, m.group().length() - 1));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        return listImgUrl;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  首先将网页的内容抓取下来,然后用正则的方式解析出网页的标签,再解析img的地址。执行程序我们可以得到下面的内容:
  http://p9.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p1.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p3.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p1.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p3.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  通过上面的地址我们就可以将图片下载到本地了,下面我们写个图片下载的方法:
  public static void main(String[] args) throws MalformedURLException, IOException {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List imgUrls = getImageSrc(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (String imgSrc : imgUrls) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  这样就很简单的实现了一个抓取并且提取图片的功能了,看起来还是比较麻烦哈,要写正则之类的 ,下面给大家介绍一种更简单的方式,如果你熟悉jQuery的话对提取元素就很简单了,这个框架就是Jsoup。
  jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
  添加jsoup的依赖:
  <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  org.jsoup<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  jsoup<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  1.11.3<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  使用jsoup之后提取的代码只需要简单的几行即可:
  public static void main(String[] args) throws MalformedURLException, IOException {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Document doc = Jsoup.parse(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Elements imgs = doc.getElementsByTag("img");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (Element img : imgs) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            String imgSrc = img.attr("src");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            if (imgSrc.startsWith("//")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                imgSrc = "http:" + imgSrc;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  通过Jsoup.parse创建一个文档对象,然后通过getElementsByTag的方法提取出所有的图片标签,循环遍历,通过attr方法获取图片的src属性,然后下载图片。
  Jsoup使用起来非常简单,当然还有很多其他解析网页的操作,大家可以去看看资料学习一下。
  下面我们再来升级一下,做成一个小工具,提供一个简单的界面,输入一个网页地址,点击提取按钮,然后把图片自动下载下来,我们可以用swing写界面。
  public class App {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static void main(String[] args) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JFrame frame = new JFrame();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setResizable(false);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setSize(425,400);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setLayout(null);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setLocationRelativeTo(null);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JTextField jTextField = new JTextField();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jTextField.setBounds(100, 44, 200, 30);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.add(jTextField);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JButton jButton = new JButton("提取");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jButton.setBounds(140, 144, 100, 30);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.add(jButton);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setVisible(true);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jButton.addActionListener(new ActionListener() {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            @Override<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            public void actionPerformed(ActionEvent e) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                String url = jTextField.getText();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                if (url == null || url.equals("")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    JOptionPane.showMessageDialog(null, "请填写抓取地址");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    return;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                Document doc = Jsoup.parse(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                Elements imgs = doc.getElementsByTag("img");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                for (Element img : imgs) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    String imgSrc = img.attr("src");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    if (imgSrc.startsWith("//")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        imgSrc = "http:" + imgSrc;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    try {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    } catch (MalformedURLException e1) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        e1.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    } catch (IOException e1) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        e1.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                JOptionPane.showMessageDialog(null, "抓取完成");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        });<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  执行main方法首先出来的就是我们的界面了,如下:
  
  屏幕快照 2018-06-18 09.50.34 PM.png
  输入地址,点击提取按钮即可下载图片。
  特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:
  
  <p class="" style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;">长按订阅更多精彩▼
  
  如有收获,点个在看,诚挚感谢</p> 查看全部

  Java做爬虫也很牛
  工具类实现比较简单,就一个get方法,读取请求地址的响应内容,这边我们用来抓取网页的内容,这边没有用代理,在真正的抓取过程中,当你大量请求某个网站的时候,对方会有一系列的策略来禁用你的请求,这个时候代理就排上用场了,通过代理设置不同的IP来抓取数据。
  import java.io.BufferedReader;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.io.InputStreamReader;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.net.HttpURLConnection;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />import java.net.URL;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />public class HttpUtils {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static String get(String url) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        try {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            URL getUrl = new URL(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            HttpURLConnection connection = (HttpURLConnection) getUrl<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    .openConnection();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestMethod("GET");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestProperty("Accept", "*/*");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    .setRequestProperty("User-Agent",<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA)");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.setRequestProperty("Accept-Language", "zh-cn");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            connection.connect();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            String line;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            StringBuffer result = new StringBuffer();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            while ((line = reader.readLine()) != null){<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                result.append(line);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            reader.close();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            return result.toString();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        } catch (Exception e) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            e.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        return null;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  接下来我们随便找一个有图片的网页,来试试抓取功能
  public static void main(String[] args) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List imgUrls = getImageSrc(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (String imgSrc : imgUrls) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            System.out.println(imgSrc);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static List getImageSrc(String html) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        // 获取img标签正则<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String IMGURL_REG = "]*?>";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        // 获取src路径的正则<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String IMGSRC_REG = "http:\"?(.*?)(\"|>|\\s+)";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Matcher matcher = Pattern.compile(IMGURL_REG).matcher(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List listImgUrl = new ArrayList();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        while (matcher.find()) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Matcher m = Pattern.compile(IMGSRC_REG).matcher(matcher.group());<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            while (m.find()) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                listImgUrl.add(m.group().substring(0, m.group().length() - 1));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        return listImgUrl;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  首先将网页的内容抓取下来,然后用正则的方式解析出网页的标签,再解析img的地址。执行程序我们可以得到下面的内容:
  http://p9.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p1.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p3.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p1.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />http://p3.pstatp.com/large/pgc ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  通过上面的地址我们就可以将图片下载到本地了,下面我们写个图片下载的方法:
  public static void main(String[] args) throws MalformedURLException, IOException {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        List imgUrls = getImageSrc(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (String imgSrc : imgUrls) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  这样就很简单的实现了一个抓取并且提取图片的功能了,看起来还是比较麻烦哈,要写正则之类的 ,下面给大家介绍一种更简单的方式,如果你熟悉jQuery的话对提取元素就很简单了,这个框架就是Jsoup。
  jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
  添加jsoup的依赖:
  <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  org.jsoup<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  jsoup<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />  1.11.3<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  使用jsoup之后提取的代码只需要简单的几行即可:
  public static void main(String[] args) throws MalformedURLException, IOException {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String url = "https://www.toutiao.com/a65683 ... %3Bbr style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Document doc = Jsoup.parse(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        Elements imgs = doc.getElementsByTag("img");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        for (Element img : imgs) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            String imgSrc = img.attr("src");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            if (imgSrc.startsWith("//")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                imgSrc = "http:" + imgSrc;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  通过Jsoup.parse创建一个文档对象,然后通过getElementsByTag的方法提取出所有的图片标签,循环遍历,通过attr方法获取图片的src属性,然后下载图片。
  Jsoup使用起来非常简单,当然还有很多其他解析网页的操作,大家可以去看看资料学习一下。
  下面我们再来升级一下,做成一个小工具,提供一个简单的界面,输入一个网页地址,点击提取按钮,然后把图片自动下载下来,我们可以用swing写界面。
  public class App {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    public static void main(String[] args) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JFrame frame = new JFrame();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setResizable(false);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setSize(425,400);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setLayout(null);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setLocationRelativeTo(null);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JTextField jTextField = new JTextField();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jTextField.setBounds(100, 44, 200, 30);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.add(jTextField);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        JButton jButton = new JButton("提取");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jButton.setBounds(140, 144, 100, 30);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.add(jButton);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        frame.setVisible(true);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        jButton.addActionListener(new ActionListener() {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            @Override<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            public void actionPerformed(ActionEvent e) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                String url = jTextField.getText();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                if (url == null || url.equals("")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    JOptionPane.showMessageDialog(null, "请填写抓取地址");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    return;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                String html = HttpUtils.get(url);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                Document doc = Jsoup.parse(html);<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                Elements imgs = doc.getElementsByTag("img");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                for (Element img : imgs) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    String imgSrc = img.attr("src");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    if (imgSrc.startsWith("//")) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        imgSrc = "http:" + imgSrc;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    try {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        Files.copy(new URL(imgSrc).openStream(), Paths.get("./img/"+UUID.randomUUID()+".png"));<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    } catch (MalformedURLException e1) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        e1.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    } catch (IOException e1) {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                        e1.printStackTrace();<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />                JOptionPane.showMessageDialog(null, "抓取完成");<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />            }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />        });<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;" />
  执行main方法首先出来的就是我们的界面了,如下:
  
  屏幕快照 2018-06-18 09.50.34 PM.png
  输入地址,点击提取按钮即可下载图片。
  特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:
  
  <p class="" style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;">长按订阅更多精彩▼
  
  如有收获,点个在看,诚挚感谢</p>

jquery抓取网页内容(我有一个包含html和文本的文本区域,我想抓取它们)

网站优化优采云 发表了文章 • 0 个评论 • 70 次浏览 • 2022-04-18 02:33 • 来自相关话题

  jquery抓取网页内容(我有一个包含html和文本的文本区域,我想抓取它们)
  我有一个收录 html 和文本的 textarea,我想从 textarea 中获取它们,但这样做似乎只能得到 html 代码而不是文本
  HTML 代码
  

<br />

<br />
Ormai sono più di 3 mesi che ho iniziato a fotografare in studio. (Per studio intendo "stanza" dove mi cemento in esperimenti fotografici :P)<br />
Il concetto principalemente rimane lo stesso, ma riuscire a controllare le luci, riflessi e gradienti è diventata quasi la mia sfida quotidiana!<br />
<br />
Ci tengo a precisare che la mia passione rimane sempre la fotografia paesaggistica, purtroppo però ho il vizio di non accontentarmi ma mai e ricerco sempre location che purtroppo non sono alla portata del viaggiatore del "week-end"<br />
<br />
In studio mi cimento spesso nell&#39; action freezing, ovvero nel congelare un movimento, che sia di liquidi o polveri.<br />
<br />
In questo caso ho usato del colorante marrone per cibo, ne ho fatto una pentola intera! La cosa essenziale è il movimento con cui realizzi lo splash...ogni movimento forma uno "shape" diverso. Spesso cambio anche contenitore...<br />
<br />
Le parti in porcellana le ho fotografate tutte singolarmente in modo da poter controllare luce, colore e gradiente.<br />
<br />
La sfida più grande è stata riuscire a fotografare il cucchiaino in acciaio. Notoriamente il metallo è riflettente e se aggiungiamo la parte concava del cucchiaio, beh, riflessi a gogo!<br />
Per ottenere un immagine prima di riflessi, in commercio ci sono dei Light Box, ovvero delle scatole formate da pareti semi trasparenti che permettono di collocare 4 o più luci estremamente, ottenendo oggetti illuminati perfettamente e senza riflessi esterni.<br />
...purtroppo io ancora non ce l&#39;ho...ed ho dovuto affidarmi al mio grande amico photoshop... e meno male che esiste! :D<br />
<br />
Una volta ottenuto tutte le parti, ed aver selezionato la splash migliore, ho unito il tutto sempre su PS.<br />
<br />
Spero che questo post sia di ispirazione!<br />
<br />
Pat.<br />
<br />
  JQUERY 代码
  $(function(){
var pcontent = $(&#39;#post&#39;).val(),
content = $($(&#39;#post&#39;).val());
console.log(content.html());
});
  这是 Jsfiddle 上用于输出的实时预览
  最佳答案
  您可以在 JQuery 中使用 .val() 直接获取这两个。
  试试这个:
  $(function(){
var pcontent = $(&#39;textarea#post&#39;).val();
console.log(pcontent);
})
  关于 javascript - 使用 jQuery 抓取文本区域内容,我们在 Stack Overflow 上发现了一个类似的问题: 查看全部

  jquery抓取网页内容(我有一个包含html和文本的文本区域,我想抓取它们)
  我有一个收录 html 和文本的 textarea,我想从 textarea 中获取它们,但这样做似乎只能得到 html 代码而不是文本
  HTML 代码
  

<br />

<br />
Ormai sono più di 3 mesi che ho iniziato a fotografare in studio. (Per studio intendo "stanza" dove mi cemento in esperimenti fotografici :P)<br />
Il concetto principalemente rimane lo stesso, ma riuscire a controllare le luci, riflessi e gradienti è diventata quasi la mia sfida quotidiana!<br />
<br />
Ci tengo a precisare che la mia passione rimane sempre la fotografia paesaggistica, purtroppo però ho il vizio di non accontentarmi ma mai e ricerco sempre location che purtroppo non sono alla portata del viaggiatore del "week-end"<br />
<br />
In studio mi cimento spesso nell&#39; action freezing, ovvero nel congelare un movimento, che sia di liquidi o polveri.<br />
<br />
In questo caso ho usato del colorante marrone per cibo, ne ho fatto una pentola intera! La cosa essenziale è il movimento con cui realizzi lo splash...ogni movimento forma uno "shape" diverso. Spesso cambio anche contenitore...<br />
<br />
Le parti in porcellana le ho fotografate tutte singolarmente in modo da poter controllare luce, colore e gradiente.<br />
<br />
La sfida più grande è stata riuscire a fotografare il cucchiaino in acciaio. Notoriamente il metallo è riflettente e se aggiungiamo la parte concava del cucchiaio, beh, riflessi a gogo!<br />
Per ottenere un immagine prima di riflessi, in commercio ci sono dei Light Box, ovvero delle scatole formate da pareti semi trasparenti che permettono di collocare 4 o più luci estremamente, ottenendo oggetti illuminati perfettamente e senza riflessi esterni.<br />
...purtroppo io ancora non ce l&#39;ho...ed ho dovuto affidarmi al mio grande amico photoshop... e meno male che esiste! :D<br />
<br />
Una volta ottenuto tutte le parti, ed aver selezionato la splash migliore, ho unito il tutto sempre su PS.<br />
<br />
Spero che questo post sia di ispirazione!<br />
<br />
Pat.<br />
<br />
  JQUERY 代码
  $(function(){
var pcontent = $(&#39;#post&#39;).val(),
content = $($(&#39;#post&#39;).val());
console.log(content.html());
});
  这是 Jsfiddle 上用于输出的实时预览
  最佳答案
  您可以在 JQuery 中使用 .val() 直接获取这两个。
  试试这个:
  $(function(){
var pcontent = $(&#39;textarea#post&#39;).val();
console.log(pcontent);
})
  关于 javascript - 使用 jQuery 抓取文本区域内容,我们在 Stack Overflow 上发现了一个类似的问题:

jquery抓取网页内容(如何让一个使用框架的网页为主要搜索引擎正确索引及如何进行优化)

网站优化优采云 发表了文章 • 0 个评论 • 61 次浏览 • 2022-04-16 00:33 • 来自相关话题

  jquery抓取网页内容(如何让一个使用框架的网页为主要搜索引擎正确索引及如何进行优化)
  谷歌开始抓取框架内容。过去很多人不相信这一点,但随着GOOGLE阅读和爬虫技术的不断深入
  发展,今天是完全可能的事情!
  什么是框架页面?
  是使用一种实现来调用其他 网站/ 页面
  当您浏览收录此内容的页面 A 时,您会看到页面 B
  论框架网页的优化技巧
  从一开始,构建 网站 就对专业的 SEO 来说也是一个挑战。是否使用框架技术来设计新的网页也成为争论的话题。在这个文章中,我们为您提供了一些基本的优化技术,同时您可以学习如何让框架页面正确索引到主要搜索引擎以及如何优化它。
  首先,我们来看看网站使用框架设计的好处。它的优越性体现在对整个网页设计完整性的维护和更新上。这就是为什么有不少网站设计师更喜欢使用框架技术进行网站设计的原因。尤其是大型网站(至少500页以上),使用框架可以让网站的维护相对容易。
  什么是框架网页?
  如果一个网页的左侧导航菜单是固定的,而页面中间的信息可以上下移动,那么一般可以认为是一个带框的网页。此外,一些带框的网站模板在其页面顶部有公司的徽标或图像。但是,这块也是固定的。页面的其余部分可以上下左右移动。一些框架站点模板还在其固定区域放置链接或导航按钮。另外,在加框的网页中,深层页面的域名通常不会反映在 URL 中(这意味着在浏览器的 URL 栏中,不会显示您当前正在查看的深层页面,而是主页)。
  在一般结构的网站中不存在这种问题。
  您可以阅读很多关于 SEO 的 文章,无论是在好书还是在网上。在这些文章中,基本认为网站用框架来设计是极其不可取的。这是因为大多数搜索引擎无法识别网页中的框架,或者无法遍历或搜索框架中的内容。
  在这种情况下,其他人可能会告诉您,使用框架的 网站 永远无法被搜索引擎索引并且无法很好地优化。这个论点好坏参半。如果框架使用得当,这个论点是站不住脚的。但是对于框架的错误使用,或者网站的设计没有考虑到当今搜索引擎技术的方方面面,那么这句话还是有些道理的。 查看全部

  jquery抓取网页内容(如何让一个使用框架的网页为主要搜索引擎正确索引及如何进行优化)
  谷歌开始抓取框架内容。过去很多人不相信这一点,但随着GOOGLE阅读和爬虫技术的不断深入
  发展,今天是完全可能的事情!
  什么是框架页面?
  是使用一种实现来调用其他 网站/ 页面
  当您浏览收录此内容的页面 A 时,您会看到页面 B
  论框架网页的优化技巧
  从一开始,构建 网站 就对专业的 SEO 来说也是一个挑战。是否使用框架技术来设计新的网页也成为争论的话题。在这个文章中,我们为您提供了一些基本的优化技术,同时您可以学习如何让框架页面正确索引到主要搜索引擎以及如何优化它。
  首先,我们来看看网站使用框架设计的好处。它的优越性体现在对整个网页设计完整性的维护和更新上。这就是为什么有不少网站设计师更喜欢使用框架技术进行网站设计的原因。尤其是大型网站(至少500页以上),使用框架可以让网站的维护相对容易。
  什么是框架网页?
  如果一个网页的左侧导航菜单是固定的,而页面中间的信息可以上下移动,那么一般可以认为是一个带框的网页。此外,一些带框的网站模板在其页面顶部有公司的徽标或图像。但是,这块也是固定的。页面的其余部分可以上下左右移动。一些框架站点模板还在其固定区域放置链接或导航按钮。另外,在加框的网页中,深层页面的域名通常不会反映在 URL 中(这意味着在浏览器的 URL 栏中,不会显示您当前正在查看的深层页面,而是主页)。
  在一般结构的网站中不存在这种问题。
  您可以阅读很多关于 SEO 的 文章,无论是在好书还是在网上。在这些文章中,基本认为网站用框架来设计是极其不可取的。这是因为大多数搜索引擎无法识别网页中的框架,或者无法遍历或搜索框架中的内容。
  在这种情况下,其他人可能会告诉您,使用框架的 网站 永远无法被搜索引擎索引并且无法很好地优化。这个论点好坏参半。如果框架使用得当,这个论点是站不住脚的。但是对于框架的错误使用,或者网站的设计没有考虑到当今搜索引擎技术的方方面面,那么这句话还是有些道理的。

jquery抓取网页内容(我的个人博客技术栈变更与我感受中的前端技术发展)

网站优化优采云 发表了文章 • 0 个评论 • 49 次浏览 • 2022-04-14 13:31 • 来自相关话题

  jquery抓取网页内容(我的个人博客技术栈变更与我感受中的前端技术发展)
  概述
  这次的标题非常抢眼。这个文章其实是想谈谈我个人博客的技术栈的变化以及我的感受中的前端技术的发展。
  事实上,对我来说,博客这个词似乎是上个世纪的事情。小时候微博很流行。我是在微博之后才知道写博客的。2017年左右,突然想找个地方输出文字,做一些记录。当时我注册了一个微信公众号,直到2019年才开始搭建这个个人博客。其实建博客可以说是酒鬼不喝酒的本意。成熟的博客生成应用相当多,不用自己折腾。但是当时我在宣传的时候买了一台阿里云服务器,只是想学习一些前端技术。这个博客是关于它应运而生的。
  有时是为了实现一些功能,学习一些新技术,有时恰恰相反,把一些新东西应用到博客上,使博客成为一个完整的“冗余项目”。我博客的技术栈发生了变化,也就是刚好成为我个人技术栈的成长过程,就在这里记录一下,顺便记录一下使用NextJS的心得。
  模板渲染、Session 和 jQuery
  一开始,作为一个主要使用Python的后端程序员,我尝试使用Django开发博客。Django 是一个遵循 MVC 模型的 Web 框架。Python相关的应用一般性能不强,所以Django的主要卖点是快速交付、内置用户系统、管理后台、模型迁移等。博客的初始版本没多久。完成。
  数据库使用 MySQL,在 Django 中使用内置的模板引擎来处理前端页面:
  {% if latest_question_list %}

{% for question in latest_question_list %}
{{ question.question_text }}
{% endfor %}

{% else %}
<p>No polls are available.
{% endif %}
</p>
  将静态文件放在约定的文件夹中,使用 nginx 代理。UI风格主要是通过BootStrap。毕竟我对CSS真的很陌生,有些页面动画也是通过框架或者搜索一些jQuery代码来解决的。这里有很多 Doucet 的博客。
  Django内置了用户和组模型,管理后台也内置。登录认证也是通过默认的Session中间件实现的,OAuth登录是通过第三方库实现的。基本上,没有时间花在这些方面。最开始博客开通了登录注册和评论功能可以通过Github登录,但是后来被认为没有必要的时候就删除了。这里 UI 和业务代码是完全紧密联系在一起的。
  RESTful、Docker 和 TLS
  由于工作原因,我开始向全栈方向发展,开始学习JavaScript。在此之前,我经常听到三个前端框架的名字。因为一不小心加了一个 React 组,就开始学习 React。这段时间,我先把博客的后端部分提取出来,并借助Django REST框架库快速完成了这部分工作,力图使接口符合RESTful规范。毕竟,应用程序很简单,没有什么可以妥协或违反规范的。注释 去掉了这个功能,但是仍然保留了登录界面,所以做了一个JWT登录认证界面,后来删掉了。Django 部分的其余部分不再关心如何呈现用户界面,
  我的服务器操作系统是 Ubuntu 18.04。在最初的部署过程中,我们需要考虑 Python 版本,以及 nginx 和 MySQL 的安装。如果以后需要迁移服务器(毕竟阿里云学生机活动才两年),也比较麻烦,所以我用了Docker,写好镜像文件后,运行容器。
  在安全问题和钱包的取舍中,​​我选择了 Let's Encypt 的免费证书来实现 HTTPS,安装简单,每三个月自动更新一次。
  SPA和SSR
  在项目中成功使用React作为管理后台后,开始考虑在博客中使用。但是通常都是开发SPA单页应用,怎么解决SEO问题呢?
  之前,我使用 Django 的模板引擎进行服务器端渲染,即在返回响应之前,我已经将 文章 内容和其他数据插入到 HTML 文件中,最终用户在浏览器中获取静态文件。如果用户请求到另一个页面,那么他会得到一个完全不同的静态文件。
  用 React 编写的 SPA 在客户端渲染,使用虚拟 DOM,整个应用程序往往只有一个 HTML 文件,切换页面不会重新请求新页面,而是替换需要更改的组件。
  那么两者的优劣势就很明显了。传统的服务器端渲染(SSR),首页打开速度更快,因为一次不会加载太多内容,对搜索引擎也很友好。毕竟爬虫可以直接获取到一个收录数据的静态 HTML 文件,但是切换页面需要替换整个页面并重新渲染,而且前后端、表现层和业务层是紧耦合的;单页应用在客户端渲染,页面切换快,数据异步获取,前后端分离,但由于首次访问获取整个应用资源,首屏加载慢,在客户端由JS渲染,爬虫很难获取到需要的数据,
  NextJS:页面、路由和自定义应用
  通过 React 和 SEO 这两个关键词,我发现了 NextJS,即 React 脚手架。在它的官网上,我看到了关键词SSR服务端渲染。前端经过多年的发展会倒退吗?当然不是,历史的发展总是螺旋式上升的,这里的SSR不同于传统的方式。准确的说,这个技术应该叫SSG静态站点生成或者Jamstack。
  NextJS 采用常规路由。pages目录下的文件名,如about.js,对应URL /about,默认导出的组件为页面组件。比较特别的是index.js对应的是/。除此之外,还有动态路由,它要求文件名用方括号括起来,例如 [tag].js。可以匹配/a、/someThing、/?tag=crumb等。 pages目录默认为页面级组件,共享组件放在src/component。
  框架提供了useRoute Hook,方便我们使用路由api。这里主要是希望在页面切换时监听切换事件,改变加载状态,改善弱网环境下的用户体验(其实很难看到这个切换过程,后面的原因又来了)。监听路由切换很方便,但是如果每个页面都需要注册一次监听,并且在组件卸载的时候取消监听,会出现太多重复的代码。
  NextJS 提供了修改容器组件的功能,在 pages 文件夹中新建一个 _app.js:
  // _app.tsx节选
function MyApp({ Component, pageProps }: AppProps) {
const [loading, setLoading] = useState(false)
const router = useRouter()
const startLoading = () => {
console.log(&#39;route change start&#39;)
setLoading(true)
}
const stopLoading = () => {
console.log(&#39;route change complete&#39;)
setLoading(false)
}
useEffect(() => {
router.events.on(&#39;routeChangeStart&#39;, startLoading)
router.events.on(&#39;routeChangeComplete&#39;, stopLoading)
router.events.on(&#39;routeChangeError&#39;, stopLoading)
return () => {
router.events.off(&#39;routeChangeStart&#39;, startLoading)
router.events.off(&#39;routeChangeComplete&#39;, stopLoading)
router.events.on(&#39;routeChangeError&#39;, stopLoading)
}
}, [])
return (





{`
body {
background-color: #f6f6f6
};
`}

)
}
  上面代码中使用了内置的css-in-component,一种内联样式的写法。我当时使用的 React 版本已经有了 Hooks。我在整个博客代码中使用了功能组件。其实这里也可以使用类组件。
  数据获取
  前面提到过,NextJS 允许搜索引擎获取预渲染的、带有数据的静态页面,那么如何在 Next 中获取数据呢?
  CI/CD、无服务器和 GraphQL
  一开始打算用Github Actions进行自动部署,但碰巧遇到了Next更新,而且Next所属的Vercel云服务比较好用,所以选择了官方推荐的方式,只要你提供一个链接到 git 仓库,Vercel 会在每次推送后自动以 serverless 的形式部署,并提供域名和 HTTPS 证书(其实就是 Let's Encypt 的证书)。
  此时,我想将后端转换为无服务器应用程序。顺便发现了hasura,它可以提供免费的GraphQL服务。只要有 postgresql 数据库,就可以生成基于 GraphQL 的后端。简单的CRUD完全没问题,所以没有继续折腾。但是对于前端,我只是想在构建过程中获取数据。Apollo 对我来说太重了,所以我找到了 graphql-request 库,它基本上只是对 fetch 的简单封装,足够使用 .
  // 示例
const response = await request(GraphQLEndpoint, query, variables)
  Link、Shallow Routing、Screening Paging 前面提到,服务器端渲染在切换页面的速度上存在缺陷,因为请求新页面需要返回新页面的完整静态文件,即使大部分页面布局没有改变了。Next 提供的 Link 组件,默认会在空闲时自动请求 JSON 数据,这样当用户点击链接时,可以快速改变内容,渲染新的页面。这也是因为我在非弱网络环境中看到了这一点。没有页面加载效果。
  在我的博客中,我为 文章 模型设置了很多外键,例如 文章 列、标签和分页。如果我想为这些设置页面,Next 提供了一种避免重新抓取的方法。浅路由,获取数据更新页面的方式:
  // 代码节选
route.push(`/posts?column=${item.column.name}`, undefined, { shallow: true })}>{item.column.name}
const route = useRoute()
useEffect(() => {
if (column) {
setArticles(articles => sourceArticles.filter(article => article.column.name === route.query.column))
}
console.log(articles)
}, [route.query.column])
  在useEffect的Hook中,根据route.query.column的变化判断是否更新文章数据源,过滤即可,无需重新取数据,并且页面仅部分更新。
  但是我很贪心,想用静态模式,每次只获取过滤需要的数据,而不是一次性获取所有数据,在客户端进行过滤,这个可以借助帮助动态路由的(这里我使用 TypeScript,Next 完全支持 TS):
  pages
├── about.tsx
├── _app.tsx
├── posts
│ └── [id].tsx
├── series.tsx
└── [column]
│ └── [page].tsx
├── [tag]
│ └── [page].tsx
└── [page].tsx
  但是这种形式,对栏目、标签、页面的过滤其实就是首页列表页,导致只有getStaticPaths函数不同,其余都是重复代码,不能接受,只有这样才可以接受 /[column]/[page 的路由,但不接受 /column=Python&amp;page=2 的查询形式。
  那么有没有办法一次接受所有的动态路由呢?其实有,一个叫[...slug]的页面组件就可以了,但是参数只能是数组,比如['a','b']对应/a/b,所以可以' t 区分Column和tag,并且如上所述,不能以查询参数的形式访问。
  在这方面,有一个问题。在某个版本中可以实现getStaticParams等API。对于博客等小数据的应用,使用 Shallow Routing 完全没问题,但对于 知乎 这样的大平台,过滤、搜索、分页都是必不可少的。
  下一步
  现在我博客原有的Django部分已经完全废弃了,自然不能使用Django提供的管理后台。Blazor在上一篇文章文章中介绍过,预计还要几个周末才能到。构建 SPA 后端。毕竟后端应用不需要SEO,SPA会更合适。CSharp 用于编写前端。过去,JS 渗透到桌面和移动端。反过来,静态语言开始蚕食 web 前端。
  总的来说,这个博客的不断重建过程,也是我学习一些前端技巧的一个实验过程。在这个过程中,我感觉自己经历了前端技术的发展变化。工程化、系统化,随着Node和一些框架的发展,前端开发体验也在不断提升。博客本身就变成了一个实验室,各种事情轮番经历。这个过程暂时不会停止。毕竟,业余时间写代码是很有趣的。博客已开源。 查看全部

  jquery抓取网页内容(我的个人博客技术栈变更与我感受中的前端技术发展)
  概述
  这次的标题非常抢眼。这个文章其实是想谈谈我个人博客的技术栈的变化以及我的感受中的前端技术的发展。
  事实上,对我来说,博客这个词似乎是上个世纪的事情。小时候微博很流行。我是在微博之后才知道写博客的。2017年左右,突然想找个地方输出文字,做一些记录。当时我注册了一个微信公众号,直到2019年才开始搭建这个个人博客。其实建博客可以说是酒鬼不喝酒的本意。成熟的博客生成应用相当多,不用自己折腾。但是当时我在宣传的时候买了一台阿里云服务器,只是想学习一些前端技术。这个博客是关于它应运而生的。
  有时是为了实现一些功能,学习一些新技术,有时恰恰相反,把一些新东西应用到博客上,使博客成为一个完整的“冗余项目”。我博客的技术栈发生了变化,也就是刚好成为我个人技术栈的成长过程,就在这里记录一下,顺便记录一下使用NextJS的心得。
  模板渲染、Session 和 jQuery
  一开始,作为一个主要使用Python的后端程序员,我尝试使用Django开发博客。Django 是一个遵循 MVC 模型的 Web 框架。Python相关的应用一般性能不强,所以Django的主要卖点是快速交付、内置用户系统、管理后台、模型迁移等。博客的初始版本没多久。完成。
  数据库使用 MySQL,在 Django 中使用内置的模板引擎来处理前端页面:
  {% if latest_question_list %}

{% for question in latest_question_list %}
{{ question.question_text }}
{% endfor %}

{% else %}
<p>No polls are available.
{% endif %}
</p>
  将静态文件放在约定的文件夹中,使用 nginx 代理。UI风格主要是通过BootStrap。毕竟我对CSS真的很陌生,有些页面动画也是通过框架或者搜索一些jQuery代码来解决的。这里有很多 Doucet 的博客。
  Django内置了用户和组模型,管理后台也内置。登录认证也是通过默认的Session中间件实现的,OAuth登录是通过第三方库实现的。基本上,没有时间花在这些方面。最开始博客开通了登录注册和评论功能可以通过Github登录,但是后来被认为没有必要的时候就删除了。这里 UI 和业务代码是完全紧密联系在一起的。
  RESTful、Docker 和 TLS
  由于工作原因,我开始向全栈方向发展,开始学习JavaScript。在此之前,我经常听到三个前端框架的名字。因为一不小心加了一个 React 组,就开始学习 React。这段时间,我先把博客的后端部分提取出来,并借助Django REST框架库快速完成了这部分工作,力图使接口符合RESTful规范。毕竟,应用程序很简单,没有什么可以妥协或违反规范的。注释 去掉了这个功能,但是仍然保留了登录界面,所以做了一个JWT登录认证界面,后来删掉了。Django 部分的其余部分不再关心如何呈现用户界面,
  我的服务器操作系统是 Ubuntu 18.04。在最初的部署过程中,我们需要考虑 Python 版本,以及 nginx 和 MySQL 的安装。如果以后需要迁移服务器(毕竟阿里云学生机活动才两年),也比较麻烦,所以我用了Docker,写好镜像文件后,运行容器。
  在安全问题和钱包的取舍中,​​我选择了 Let's Encypt 的免费证书来实现 HTTPS,安装简单,每三个月自动更新一次。
  SPA和SSR
  在项目中成功使用React作为管理后台后,开始考虑在博客中使用。但是通常都是开发SPA单页应用,怎么解决SEO问题呢?
  之前,我使用 Django 的模板引擎进行服务器端渲染,即在返回响应之前,我已经将 文章 内容和其他数据插入到 HTML 文件中,最终用户在浏览器中获取静态文件。如果用户请求到另一个页面,那么他会得到一个完全不同的静态文件。
  用 React 编写的 SPA 在客户端渲染,使用虚拟 DOM,整个应用程序往往只有一个 HTML 文件,切换页面不会重新请求新页面,而是替换需要更改的组件。
  那么两者的优劣势就很明显了。传统的服务器端渲染(SSR),首页打开速度更快,因为一次不会加载太多内容,对搜索引擎也很友好。毕竟爬虫可以直接获取到一个收录数据的静态 HTML 文件,但是切换页面需要替换整个页面并重新渲染,而且前后端、表现层和业务层是紧耦合的;单页应用在客户端渲染,页面切换快,数据异步获取,前后端分离,但由于首次访问获取整个应用资源,首屏加载慢,在客户端由JS渲染,爬虫很难获取到需要的数据,
  NextJS:页面、路由和自定义应用
  通过 React 和 SEO 这两个关键词,我发现了 NextJS,即 React 脚手架。在它的官网上,我看到了关键词SSR服务端渲染。前端经过多年的发展会倒退吗?当然不是,历史的发展总是螺旋式上升的,这里的SSR不同于传统的方式。准确的说,这个技术应该叫SSG静态站点生成或者Jamstack。
  NextJS 采用常规路由。pages目录下的文件名,如about.js,对应URL /about,默认导出的组件为页面组件。比较特别的是index.js对应的是/。除此之外,还有动态路由,它要求文件名用方括号括起来,例如 [tag].js。可以匹配/a、/someThing、/?tag=crumb等。 pages目录默认为页面级组件,共享组件放在src/component。
  框架提供了useRoute Hook,方便我们使用路由api。这里主要是希望在页面切换时监听切换事件,改变加载状态,改善弱网环境下的用户体验(其实很难看到这个切换过程,后面的原因又来了)。监听路由切换很方便,但是如果每个页面都需要注册一次监听,并且在组件卸载的时候取消监听,会出现太多重复的代码。
  NextJS 提供了修改容器组件的功能,在 pages 文件夹中新建一个 _app.js:
  // _app.tsx节选
function MyApp({ Component, pageProps }: AppProps) {
const [loading, setLoading] = useState(false)
const router = useRouter()
const startLoading = () => {
console.log(&#39;route change start&#39;)
setLoading(true)
}
const stopLoading = () => {
console.log(&#39;route change complete&#39;)
setLoading(false)
}
useEffect(() => {
router.events.on(&#39;routeChangeStart&#39;, startLoading)
router.events.on(&#39;routeChangeComplete&#39;, stopLoading)
router.events.on(&#39;routeChangeError&#39;, stopLoading)
return () => {
router.events.off(&#39;routeChangeStart&#39;, startLoading)
router.events.off(&#39;routeChangeComplete&#39;, stopLoading)
router.events.on(&#39;routeChangeError&#39;, stopLoading)
}
}, [])
return (





{`
body {
background-color: #f6f6f6
};
`}

)
}
  上面代码中使用了内置的css-in-component,一种内联样式的写法。我当时使用的 React 版本已经有了 Hooks。我在整个博客代码中使用了功能组件。其实这里也可以使用类组件。
  数据获取
  前面提到过,NextJS 允许搜索引擎获取预渲染的、带有数据的静态页面,那么如何在 Next 中获取数据呢?
  CI/CD、无服务器和 GraphQL
  一开始打算用Github Actions进行自动部署,但碰巧遇到了Next更新,而且Next所属的Vercel云服务比较好用,所以选择了官方推荐的方式,只要你提供一个链接到 git 仓库,Vercel 会在每次推送后自动以 serverless 的形式部署,并提供域名和 HTTPS 证书(其实就是 Let's Encypt 的证书)。
  此时,我想将后端转换为无服务器应用程序。顺便发现了hasura,它可以提供免费的GraphQL服务。只要有 postgresql 数据库,就可以生成基于 GraphQL 的后端。简单的CRUD完全没问题,所以没有继续折腾。但是对于前端,我只是想在构建过程中获取数据。Apollo 对我来说太重了,所以我找到了 graphql-request 库,它基本上只是对 fetch 的简单封装,足够使用 .
  // 示例
const response = await request(GraphQLEndpoint, query, variables)
  Link、Shallow Routing、Screening Paging 前面提到,服务器端渲染在切换页面的速度上存在缺陷,因为请求新页面需要返回新页面的完整静态文件,即使大部分页面布局没有改变了。Next 提供的 Link 组件,默认会在空闲时自动请求 JSON 数据,这样当用户点击链接时,可以快速改变内容,渲染新的页面。这也是因为我在非弱网络环境中看到了这一点。没有页面加载效果。
  在我的博客中,我为 文章 模型设置了很多外键,例如 文章 列、标签和分页。如果我想为这些设置页面,Next 提供了一种避免重新抓取的方法。浅路由,获取数据更新页面的方式:
  // 代码节选
route.push(`/posts?column=${item.column.name}`, undefined, { shallow: true })}>{item.column.name}
const route = useRoute()
useEffect(() => {
if (column) {
setArticles(articles => sourceArticles.filter(article => article.column.name === route.query.column))
}
console.log(articles)
}, [route.query.column])
  在useEffect的Hook中,根据route.query.column的变化判断是否更新文章数据源,过滤即可,无需重新取数据,并且页面仅部分更新。
  但是我很贪心,想用静态模式,每次只获取过滤需要的数据,而不是一次性获取所有数据,在客户端进行过滤,这个可以借助帮助动态路由的(这里我使用 TypeScript,Next 完全支持 TS):
  pages
├── about.tsx
├── _app.tsx
├── posts
│ └── [id].tsx
├── series.tsx
└── [column]
│ └── [page].tsx
├── [tag]
│ └── [page].tsx
└── [page].tsx
  但是这种形式,对栏目、标签、页面的过滤其实就是首页列表页,导致只有getStaticPaths函数不同,其余都是重复代码,不能接受,只有这样才可以接受 /[column]/[page 的路由,但不接受 /column=Python&amp;page=2 的查询形式。
  那么有没有办法一次接受所有的动态路由呢?其实有,一个叫[...slug]的页面组件就可以了,但是参数只能是数组,比如['a','b']对应/a/b,所以可以' t 区分Column和tag,并且如上所述,不能以查询参数的形式访问。
  在这方面,有一个问题。在某个版本中可以实现getStaticParams等API。对于博客等小数据的应用,使用 Shallow Routing 完全没问题,但对于 知乎 这样的大平台,过滤、搜索、分页都是必不可少的。
  下一步
  现在我博客原有的Django部分已经完全废弃了,自然不能使用Django提供的管理后台。Blazor在上一篇文章文章中介绍过,预计还要几个周末才能到。构建 SPA 后端。毕竟后端应用不需要SEO,SPA会更合适。CSharp 用于编写前端。过去,JS 渗透到桌面和移动端。反过来,静态语言开始蚕食 web 前端。
  总的来说,这个博客的不断重建过程,也是我学习一些前端技巧的一个实验过程。在这个过程中,我感觉自己经历了前端技术的发展变化。工程化、系统化,随着Node和一些框架的发展,前端开发体验也在不断提升。博客本身就变成了一个实验室,各种事情轮番经历。这个过程暂时不会停止。毕竟,业余时间写代码是很有趣的。博客已开源。

jquery抓取网页内容(使用HtmlAgilityPack一段时间.....推荐答案)

网站优化优采云 发表了文章 • 0 个评论 • 55 次浏览 • 2022-04-14 11:24 • 来自相关话题

  jquery抓取网页内容(使用HtmlAgilityPack一段时间.....推荐答案)
  问题描述
  我已经使用 HtmlAgilityPack 有一段时间了,但是我现在使用的 Web 资源有一个(看起来像)浏览器通过的 jQuery 协议。我希望加载的是产品页面,但实际加载的是(通过 WebBrowser 控件和 WebClient DownloadString Verification)是一个重定向,它要求访问者选择顾问并与他们注册。
  换句话说,使用 Chrome 的 Inspect &gt;&gt; Elements 工具,我得到:
  


  但是 WebBrowser 和 HTMLAgilityPack 只能得到:
  


&times;

It looks like you haven't selected a Consultant yet!
<p style="text-align: center;">...were you just wanting to browse or were you looking to shop and pick a Consultant to shop under?


...
</p>
  在深入研究标题的类定义后,我发现页面确实使用 jQuery 来处理正确的加载,并在访问者浏览页面时处理操作(滚动、调整大小、悬停在图像上、选择其他图像等)。这是来自 jQuery 的标头:
  /*!
* jQuery JavaScript Library v2.1.4
* http://jquery.com/
*
* Includes Sizzle.js
* http://sizzlejs.com/
*
* Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2015-04-28T16:01Z
*/
  我按照此处所述尝试了 ScrapySharp:C# .NET: Scraping Dynamics (JS) 网站
  但这最终会消耗所有可用内存并且什么也不会产生。
  这也是:htmlagilitypack 和动态内容问题加载错误重定向如上。
  如果需要,我可以提供更多我试图从中提取的源代码,包括完整的 jQuery。
  推荐答案
  使用 CaptureRedirect = false; 绕过重定向页面。对于您提到的页面,这对我有用:
  var web = new HtmlWeb();
web.CaptureRedirect = false;
web.BrowserTimeout = TimeSpan.FromSeconds(15);
  现在继续尝试,直到您在页面上看到文本“产品描述”。
  var doc = web.LoadFromBrowser(url, html =>
{
return html.Contains("Product Description");
});
  最新版本的 HtmlAgilityPack 可以在后台运行浏览器。所以我们真的不需要像 ScrapySharp 这样的库来抓取动态内容。 查看全部

  jquery抓取网页内容(使用HtmlAgilityPack一段时间.....推荐答案)
  问题描述
  我已经使用 HtmlAgilityPack 有一段时间了,但是我现在使用的 Web 资源有一个(看起来像)浏览器通过的 jQuery 协议。我希望加载的是产品页面,但实际加载的是(通过 WebBrowser 控件和 WebClient DownloadString Verification)是一个重定向,它要求访问者选择顾问并与他们注册。
  换句话说,使用 Chrome 的 Inspect &gt;&gt; Elements 工具,我得到:
  


  但是 WebBrowser 和 HTMLAgilityPack 只能得到:
  


&times;

It looks like you haven't selected a Consultant yet!
<p style="text-align: center;">...were you just wanting to browse or were you looking to shop and pick a Consultant to shop under?


...
</p>
  在深入研究标题的类定义后,我发现页面确实使用 jQuery 来处理正确的加载,并在访问者浏览页面时处理操作(滚动、调整大小、悬停在图像上、选择其他图像等)。这是来自 jQuery 的标头:
  /*!
* jQuery JavaScript Library v2.1.4
* http://jquery.com/
*
* Includes Sizzle.js
* http://sizzlejs.com/
*
* Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2015-04-28T16:01Z
*/
  我按照此处所述尝试了 ScrapySharp:C# .NET: Scraping Dynamics (JS) 网站
  但这最终会消耗所有可用内存并且什么也不会产生。
  这也是:htmlagilitypack 和动态内容问题加载错误重定向如上。
  如果需要,我可以提供更多我试图从中提取的源代码,包括完整的 jQuery。
  推荐答案
  使用 CaptureRedirect = false; 绕过重定向页面。对于您提到的页面,这对我有用:
  var web = new HtmlWeb();
web.CaptureRedirect = false;
web.BrowserTimeout = TimeSpan.FromSeconds(15);
  现在继续尝试,直到您在页面上看到文本“产品描述”。
  var doc = web.LoadFromBrowser(url, html =>
{
return html.Contains("Product Description");
});
  最新版本的 HtmlAgilityPack 可以在后台运行浏览器。所以我们真的不需要像 ScrapySharp 这样的库来抓取动态内容。

jquery抓取网页内容(服务器君一共花费了5.978ms进行了6次数据库查询)

网站优化优采云 发表了文章 • 0 个评论 • 118 次浏览 • 2022-04-14 02:22 • 来自相关话题

  jquery抓取网页内容(服务器君一共花费了5.978ms进行了6次数据库查询)
  服务器总共花费了 5.978 ms 进行了 6 次数据库查询,努力为您提供了这个页面。
  使用 JQuery 添加、获取和更改 HTML 元素的内容非常容易,而且您会对这种简单性感到非常满意。我们先来看看demo:
  效果演示
  欢迎来到简明现代魔法图书馆
  html() 方法
  此方法类似于 JavaScript 中的 innerHTML 属性,可用于读取或设置元素的 HTML 内容。要获取元素的内容,可以这样做:
  
var p_html = $("p").html(); //获取p元素的HTML代码
  如果需要设置元素的HTML代码,也可以使用该方法,但需要为其传递参数。例如设置p元素的HTML代码,可以使用如下代码:
  
//设置p元素的HTML代码
$("p").html("欢迎您访问简明现代魔法图书馆~~");
  注意:html() 方法可以用于 XHTML 文档,但不能用于 XML 文档。
  text() 方法
  此方法类似于 JavaScript 中的 innerText 属性,可用于读取或取消设置元素的文本内容。继续使用上面的HTML代码,使用text()方法对p元素进行操作:
  
var p_text = $("p").text(); //获取p元素的文本内容
  和html()方法一样,如果需要给一个元素设置文本内容,也需要传一个参数。比如设置p元素的文本内容,代码如下:
  
// 设置p元素的文本内容
$("p").text("欢迎您访问简明现代魔法图书馆~~");
  注意以下两点:
  JavaScript 中的 innerText 属性在 Firefox 浏览器中不起作用,而 jQuery 的 text() 方法支持所有浏览器。 text() 方法适用于 HTML 文档和 XML 文档。 查看全部

  jquery抓取网页内容(服务器君一共花费了5.978ms进行了6次数据库查询)
  服务器总共花费了 5.978 ms 进行了 6 次数据库查询,努力为您提供了这个页面。
  使用 JQuery 添加、获取和更改 HTML 元素的内容非常容易,而且您会对这种简单性感到非常满意。我们先来看看demo:
  效果演示
  欢迎来到简明现代魔法图书馆
  html() 方法
  此方法类似于 JavaScript 中的 innerHTML 属性,可用于读取或设置元素的 HTML 内容。要获取元素的内容,可以这样做:
  
var p_html = $("p").html(); //获取p元素的HTML代码
  如果需要设置元素的HTML代码,也可以使用该方法,但需要为其传递参数。例如设置p元素的HTML代码,可以使用如下代码:
  
//设置p元素的HTML代码
$("p").html("欢迎您访问简明现代魔法图书馆~~");
  注意:html() 方法可以用于 XHTML 文档,但不能用于 XML 文档。
  text() 方法
  此方法类似于 JavaScript 中的 innerText 属性,可用于读取或取消设置元素的文本内容。继续使用上面的HTML代码,使用text()方法对p元素进行操作:
  
var p_text = $("p").text(); //获取p元素的文本内容
  和html()方法一样,如果需要给一个元素设置文本内容,也需要传一个参数。比如设置p元素的文本内容,代码如下:
  
// 设置p元素的文本内容
$("p").text("欢迎您访问简明现代魔法图书馆~~");
  注意以下两点:
  JavaScript 中的 innerText 属性在 Firefox 浏览器中不起作用,而 jQuery 的 text() 方法支持所有浏览器。 text() 方法适用于 HTML 文档和 XML 文档。

jquery抓取网页内容(亿速云行业资讯频道频道详细介绍,介绍介绍)

网站优化优采云 发表了文章 • 0 个评论 • 49 次浏览 • 2022-04-12 00:21 • 来自相关话题

  jquery抓取网页内容(亿速云行业资讯频道频道详细介绍,介绍介绍)
  这篇文章主要介绍jquery获取html元素内容的方法。很详细,有一定的参考价值。有兴趣的朋友一定要读一读!
  jquery获取html元素内容的方法:1、使用html()返回被选中元素的内容,语法“$(selector).html()”;2、使用text()返回被选中元素的文本内容,语法“$(selector).text()”。
  1、html():返回原创HTML文档,但在IE中可能有兼容性,如下
  

Document
<p id="box">
<p class="b2">我是一个p元素
你好
</p>
$(function(){
var str = $("#box").html();
console.log(str);
//
  我是一个p元素
// 你好
//解释:该方法使用的是JS中的innerHTML()有些浏览器返回的结果可能不是原始文档的 HTML 源代码。例如,如果属性值只包含字母数字字符,Internet Explorer有时丢弃包裹属性值的引号
});
</p>
  2、text():获取匹配元素集中每个元素的组合文本,包括它们的后代
  

Document
<p id="box">
<p class="b2">我是一个p元素
你好
</p>
$(function(){ var str = $("#box").text();
console.log(str); // 我是一个p元素
// 你好 });
</p>
  3、val() 方法
  以上就是jquery获取html元素内容的方法的全部内容,感谢阅读!希望分享的内容对您有所帮助。更多相关知识,请关注易宿云行业资讯频道! 查看全部

  jquery抓取网页内容(亿速云行业资讯频道频道详细介绍,介绍介绍)
  这篇文章主要介绍jquery获取html元素内容的方法。很详细,有一定的参考价值。有兴趣的朋友一定要读一读!
  jquery获取html元素内容的方法:1、使用html()返回被选中元素的内容,语法“$(selector).html()”;2、使用text()返回被选中元素的文本内容,语法“$(selector).text()”。
  1、html():返回原创HTML文档,但在IE中可能有兼容性,如下
  

Document
<p id="box">
<p class="b2">我是一个p元素
你好
</p>
$(function(){
var str = $("#box").html();
console.log(str);
//
  我是一个p元素
// 你好
//解释:该方法使用的是JS中的innerHTML()有些浏览器返回的结果可能不是原始文档的 HTML 源代码。例如,如果属性值只包含字母数字字符,Internet Explorer有时丢弃包裹属性值的引号
});
</p>
  2、text():获取匹配元素集中每个元素的组合文本,包括它们的后代
  

Document
<p id="box">
<p class="b2">我是一个p元素
你好
</p>
$(function(){ var str = $("#box").text();
console.log(str); // 我是一个p元素
// 你好 });
</p>
  3、val() 方法
  以上就是jquery获取html元素内容的方法的全部内容,感谢阅读!希望分享的内容对您有所帮助。更多相关知识,请关注易宿云行业资讯频道!

jquery抓取网页内容(jquery抓取网页内容方法很多,关键是要选好代理)

网站优化优采云 发表了文章 • 0 个评论 • 62 次浏览 • 2022-04-11 17:02 • 来自相关话题

  jquery抓取网页内容(jquery抓取网页内容方法很多,关键是要选好代理)
  jquery抓取网页内容方法很多,关键是要选好代理,
  jquery可以抓取网页任何部分,比如图片,比如源代码,比如json等等。手动要解析得在一两个小时,难度太大。除非你有专门的程序员,买点机器。
  浏览器上装一个插件img1pass。js进阶可以装个qq浏览器插件mlook,因为在html版本较低的时候。效果比较好的。
  javascript(和css)能力达到一定水平即可
  首先需要把数据抓取来,然后用javascript去操作加载javascript时的页面,最后可以通过json格式的网页数据拼接来提取你需要的关键字,完成真正抓取。
  之前专门研究过这个问题。抓取js就可以了。谷歌曾经有个实验,模拟浏览器进程去抓取非html,这样抓取每页的请求数会比javascript下方法多得多,效率也提高了。谷歌,百度都这么搞的,提供cookie。你也可以关注本专栏,关注不同的爬虫方法。
  不会。建议回头看看自己老板是怎么做的。
  jquery本身只是提供一个api,客户端提供的js文件可以自己处理,jquery加javascript才能执行,爬虫本身一般只提供javascriptapi,如果有需要javascript文件来传递数据,可以使用python的jquery库。
  jquery最近网上方法基本上都不适用了,缺点网页抓取本身的姿势要求还是很多,如果是想研究ui方面的,建议看requests这个库, 查看全部

  jquery抓取网页内容(jquery抓取网页内容方法很多,关键是要选好代理)
  jquery抓取网页内容方法很多,关键是要选好代理,
  jquery可以抓取网页任何部分,比如图片,比如源代码,比如json等等。手动要解析得在一两个小时,难度太大。除非你有专门的程序员,买点机器。
  浏览器上装一个插件img1pass。js进阶可以装个qq浏览器插件mlook,因为在html版本较低的时候。效果比较好的。
  javascript(和css)能力达到一定水平即可
  首先需要把数据抓取来,然后用javascript去操作加载javascript时的页面,最后可以通过json格式的网页数据拼接来提取你需要的关键字,完成真正抓取。
  之前专门研究过这个问题。抓取js就可以了。谷歌曾经有个实验,模拟浏览器进程去抓取非html,这样抓取每页的请求数会比javascript下方法多得多,效率也提高了。谷歌,百度都这么搞的,提供cookie。你也可以关注本专栏,关注不同的爬虫方法。
  不会。建议回头看看自己老板是怎么做的。
  jquery本身只是提供一个api,客户端提供的js文件可以自己处理,jquery加javascript才能执行,爬虫本身一般只提供javascriptapi,如果有需要javascript文件来传递数据,可以使用python的jquery库。
  jquery最近网上方法基本上都不适用了,缺点网页抓取本身的姿势要求还是很多,如果是想研究ui方面的,建议看requests这个库,

jquery抓取网页内容(Xpath:简单易用的网页内容提取工具学习爽,一直学习一直爽!)

网站优化优采云 发表了文章 • 0 个评论 • 63 次浏览 • 2022-04-10 23:37 • 来自相关话题

  jquery抓取网页内容(Xpath:简单易用的网页内容提取工具学习爽,一直学习一直爽!)
  Xpath:一个易于使用的网页内容提取工具
  学习一时爽,学习永远爽!
  大家好,我是康纳,一个从零开始的技术新手。上次我们讲了如何使用请求。在上一课中,我们已经学习了所有常见的 Python 访问库。那么当我们得到我们访问的内容时,我们应该从网页中提取出我们想要的内容。因此,今天我们就来聊一聊常用的网页内容提取工具之一:Xpath。与 BeautifulSoup 相比,Xpath 更易于使用。
  1.Xpath 简介
  Xpath 是一种用于在 XML 文档中查找信息的语言。XPath 用于浏览 XML 文档中的元素和属性。他是一种路径语言(XML Path Language),用来确定一个XML文档的某一部分的位置。
  XPath 基于 XML 的树结构,它提供了在数据结构树中查找节点的能力。XPath 的初衷是将其用作 XPointer 和 XSL 之间的通用语法模型。但是 XPath 很快被开发人员采用,并被广泛用作小型*查询语言。例如,当您打开网页并按 F12 进行元素检查时。当要复制元素的路径时,可以通过右键进行复制操作。您将在里面找到 Copy Xpath 的选项。这显示了 Xpath 的广泛使用。
  说了这么多Xpath的使用范围有多大,使用起来有多么简单,让我们开始做正事,看看Xpath是如何在Python爬虫中用来爬取我们想要的内容的:
  2. Xpath 安装
  在之前的教程中,我几乎没有提到某个库的安装,但为什么我在这里提到如何安装呢?原因很简单,Xpath 只是 lxml 库中的一个模块。许多 Python 库都提供了 Xpath 函数,但最基本的是 lxml 库。最有效率。所以,你知道,要使用 Xpath,你需要安装 lxml 库:
  pip install lxml
复制代码
  3.Xpath 语法
  其实说白了,Xpath就是从html中选择节点。通过以下路径或步骤选择节点。下面,我们将通过以下HTML文档进行演示:
  html_doc ="""








总裁的新鲜小妻子







斗神天下


"""
复制代码
  首先大家都知道,我们实际上从网页中得到的是字符串格式。所以如果我们想通过 Xpath 提取我们想要的东西,我们首先需要生成 HTML DOM 树:
  from lxml import etree
page = etree.HTML(html_doc)
复制代码
  3.1 路径查找
  如果我们要使用寻路,我们首先需要知道 Xpath 的语法。Xpath的主要语法如下:
  表达式描述
  节点名
  选择名为nodename的子节点
  /
  从根节点挑选
  //
  从与选择匹配的当前节点中选择文档中的节点,而不考虑它们的位置。
  .
  选择当前节点
  ..
  选择当前节点的父节点
  @
  选择属性
  In [1]: page.xpath(&#39;head&#39;)
Out[1]: []
复制代码
  当前节点位置在html中,所以可以直接查询头节点,li是html的孙子节点,如果查询li则返回空值:
  In [2]: page.xpath(&#39;li&#39;)
Out[2]: []
复制代码
  In [3]: page.xpath(&#39;/html&#39;)
Out[3]: []
复制代码
  从根节点搜索,根节点下只有一个节点html节点,所以从根节点只能找到html,如果搜索其他内容,会返回一个空列表:
  In [4]: page.xpath(&#39;/li&#39;)
Out[4]: []
复制代码
  In [5]: page.xpath(&#39;//li&#39;)
Out[5]:
[,
,
,
]
复制代码
  从整个文档中查找在整个文档中查找符合条件的节点,包括孙节点及以下。
  In [6]: page.xpath(&#39;//li&#39;)[0].xpath(&#39;..&#39;)
Out[6]: []
复制代码
  In [7]: page.xpath(&#39;//a&#39;)[1].xpath(&#39;@href&#39;)
Out[7]: [&#39;/book_16860.html&#39;]
复制代码
  选中属性支持任意标签属性,但需要注意的是,如果选中的节点有多个,需要指定是哪个节点的属性。
  3.2 节点查找
  通过路径找到节点后,我们需要从超级找到的节点中选择我们需要的内容。还有一些查找节点的语法,如下:
  表达结果
  节点名[索引]
  选择满足要求的第 index 个元素
  节点名[last()]
  选择最后一个元素
  节点名[位置()
  选择前 num 个元素
  节点名[@attribute]
  选择属性名为attribute的元素
  节点名[@attribute='值']
  选择具有属性名称属性和值值的元素
  In [1]: page.xpath(&#39;//li[1]/a[1]/img[1]/@src&#39;)
Out[1]: [&#39;/16860s.jpg&#39;]
复制代码
  **注意:选择节点的属性时需要注意一件事。[index] 选择的节点是每个条件的第 [index] 个合格元素。**不过这个比较抽象,举个例子吧。例如:
  In [2]: page.xpath(&#39;//li[1]&#39;) 选取所有符合 li 节点的第一个节点
Out[2]: []
复制代码
  从上面的例子中,我们似乎什么都看不到,那么我们来看下面的例子:
  In [3]: page.xpath(&#39;//li//img[1]&#39;)
Out[3]: [,
,
,
]
复制代码
  如您所见,我们选择了 4 个 img 节点。原因很简单,看下面的代码和解释就明白了:
  




(一)

(二)
(三)
总裁的新鲜小妻子



(四)

(五)
(六)
斗神天下


复制代码
  (一) 是第一个节点中的第一个节点
  节点。它的路径是 //
  (二) 是第一个节点的
  首先在节点
  节点。它的路径是/
  . (三) 没有被选中,因为它是标签下的第二个
  标签 (四) (五) (六)类似
  In [4]: page.xpath(&#39;//img[position()>1]&#39;)
Out[4]: [, ]
复制代码
  3.3 匹配未知节点
  当我们匹配时,会有一条不确定的路径。此时,我们将涉及匹配未知节点。匹配未知节点也有对应的语法,如下:
  通配符说明
  *
  匹配任何元素节点
  @*
  匹配任何属性节点
  匹配任意属性节点:
  In [1]: page.xpath(&#39;//li/a/*&#39;)
Out[1]: [,
,
,
]
复制代码
  匹配任何元素节点:
  In [2]: page.xpath(&#39;//li/a[@*]&#39;)
Out[2]: [,
,
,
]
复制代码
  3.4 获取节点中的文本
  可以通过attribute方法获取属性中的内容,但无法获取节点之间的内容。这时可以通过 text() 和 string() 方法获取其中的文本:
  使用 text() 获取节点中的文本:
  In [1]: page.xpath(&#39;//li/a[3]/text()&#39;)
Out[1]: [&#39;总裁的新鲜小妻子&#39;, &#39;斗神天下&#39;]
复制代码
  如您所见,标签之间的文本可以通过 text() 属性轻松获取。
  使用 string() 获取节点中的文本:
  In [1]: page.xpath(&#39;string(//li[1]/a[3])&#39;)
Out[1]: &#39;总裁的新鲜小妻子&#39;
复制代码
  3.5 选择多个路径
  有时我们需要同时查找多个条件。此时,您可以通过在路径表达式中使用竖线字符(“|”)来选择多个路径:
  In [1]: page.xpath(&#39;//li[1]/img[2]/@src | //li[1]/a[3]/text()&#39;)
Out[1]: [&#39;/kukuku/images/second.png&#39;, &#39;总裁的新鲜小妻子&#39;]
复制代码
  同时选择多条路径不会生成新的列表,只会生成一个列表,所以你需要考虑如何提取你返回的结果。一般来说,不建议使用多个条件进行搜索,因为将多个提取结果混合在一个列表中不利于提取。即使可以提取,也会增加计算量,降低程序性能。所以,尽量不要使用这种方法。
  下一条通知:
  Xpath用起来还是那么费劲,有没有其他更简单的方法?? ? 当然有,你可以用美味的汤完成你需要做的事情。敬请关注下一期 - BeautifulSoup:美味汤
  以上就是所有Xpath相关的内容了,可能没有其他的详细,但是对于你作为爬虫使用来说已经足够了。其实我也希望能详细一点,不过我是常客,个人不太喜欢用Xpath。如果你真的想深入了解 Xpth,我建议你去 W3C Xpath 教程 &gt;&gt;&gt; 看看他们是如何使用它的。
  好了,今天就到这里,我是康纳,一个从零开始的技术菜鸟。不知道你今天收获了多少?? ? 下次见!
  学习一时爽,学习永远爽!
  系列文章连接:
  Python爬虫十六种形式——第一种形式:HTTP协议&gt;&gt;&gt;
  Python爬虫十六式二:urllib和urllib3 &gt;&gt;&gt;
  Python爬虫十六式-第三式:Requests的用法&gt;&gt;&gt;
  Python爬虫十六-五:BeautifulSoup,美味的汤&gt;&gt;&gt;
  Python爬虫十六式六:JQuery的假兄弟-pyquery &gt;&gt;&gt;
  Python爬虫十六式七:正则美术&gt;&gt;&gt;
  Python爬虫十六式——第八式:实例分析——全书网&gt;&gt;&gt;
  转载于: 查看全部

  jquery抓取网页内容(Xpath:简单易用的网页内容提取工具学习爽,一直学习一直爽!)
  Xpath:一个易于使用的网页内容提取工具
  学习一时爽,学习永远爽!
  大家好,我是康纳,一个从零开始的技术新手。上次我们讲了如何使用请求。在上一课中,我们已经学习了所有常见的 Python 访问库。那么当我们得到我们访问的内容时,我们应该从网页中提取出我们想要的内容。因此,今天我们就来聊一聊常用的网页内容提取工具之一:Xpath。与 BeautifulSoup 相比,Xpath 更易于使用。
  1.Xpath 简介
  Xpath 是一种用于在 XML 文档中查找信息的语言。XPath 用于浏览 XML 文档中的元素和属性。他是一种路径语言(XML Path Language),用来确定一个XML文档的某一部分的位置。
  XPath 基于 XML 的树结构,它提供了在数据结构树中查找节点的能力。XPath 的初衷是将其用作 XPointer 和 XSL 之间的通用语法模型。但是 XPath 很快被开发人员采用,并被广泛用作小型*查询语言。例如,当您打开网页并按 F12 进行元素检查时。当要复制元素的路径时,可以通过右键进行复制操作。您将在里面找到 Copy Xpath 的选项。这显示了 Xpath 的广泛使用。
  说了这么多Xpath的使用范围有多大,使用起来有多么简单,让我们开始做正事,看看Xpath是如何在Python爬虫中用来爬取我们想要的内容的:
  2. Xpath 安装
  在之前的教程中,我几乎没有提到某个库的安装,但为什么我在这里提到如何安装呢?原因很简单,Xpath 只是 lxml 库中的一个模块。许多 Python 库都提供了 Xpath 函数,但最基本的是 lxml 库。最有效率。所以,你知道,要使用 Xpath,你需要安装 lxml 库:
  pip install lxml
复制代码
  3.Xpath 语法
  其实说白了,Xpath就是从html中选择节点。通过以下路径或步骤选择节点。下面,我们将通过以下HTML文档进行演示:
  html_doc ="""








总裁的新鲜小妻子







斗神天下


"""
复制代码
  首先大家都知道,我们实际上从网页中得到的是字符串格式。所以如果我们想通过 Xpath 提取我们想要的东西,我们首先需要生成 HTML DOM 树:
  from lxml import etree
page = etree.HTML(html_doc)
复制代码
  3.1 路径查找
  如果我们要使用寻路,我们首先需要知道 Xpath 的语法。Xpath的主要语法如下:
  表达式描述
  节点名
  选择名为nodename的子节点
  /
  从根节点挑选
  //
  从与选择匹配的当前节点中选择文档中的节点,而不考虑它们的位置。
  .
  选择当前节点
  ..
  选择当前节点的父节点
  @
  选择属性
  In [1]: page.xpath(&#39;head&#39;)
Out[1]: []
复制代码
  当前节点位置在html中,所以可以直接查询头节点,li是html的孙子节点,如果查询li则返回空值:
  In [2]: page.xpath(&#39;li&#39;)
Out[2]: []
复制代码
  In [3]: page.xpath(&#39;/html&#39;)
Out[3]: []
复制代码
  从根节点搜索,根节点下只有一个节点html节点,所以从根节点只能找到html,如果搜索其他内容,会返回一个空列表:
  In [4]: page.xpath(&#39;/li&#39;)
Out[4]: []
复制代码
  In [5]: page.xpath(&#39;//li&#39;)
Out[5]:
[,
,
,
]
复制代码
  从整个文档中查找在整个文档中查找符合条件的节点,包括孙节点及以下。
  In [6]: page.xpath(&#39;//li&#39;)[0].xpath(&#39;..&#39;)
Out[6]: []
复制代码
  In [7]: page.xpath(&#39;//a&#39;)[1].xpath(&#39;@href&#39;)
Out[7]: [&#39;/book_16860.html&#39;]
复制代码
  选中属性支持任意标签属性,但需要注意的是,如果选中的节点有多个,需要指定是哪个节点的属性。
  3.2 节点查找
  通过路径找到节点后,我们需要从超级找到的节点中选择我们需要的内容。还有一些查找节点的语法,如下:
  表达结果
  节点名[索引]
  选择满足要求的第 index 个元素
  节点名[last()]
  选择最后一个元素
  节点名[位置()
  选择前 num 个元素
  节点名[@attribute]
  选择属性名为attribute的元素
  节点名[@attribute='值']
  选择具有属性名称属性和值值的元素
  In [1]: page.xpath(&#39;//li[1]/a[1]/img[1]/@src&#39;)
Out[1]: [&#39;/16860s.jpg&#39;]
复制代码
  **注意:选择节点的属性时需要注意一件事。[index] 选择的节点是每个条件的第 [index] 个合格元素。**不过这个比较抽象,举个例子吧。例如:
  In [2]: page.xpath(&#39;//li[1]&#39;) 选取所有符合 li 节点的第一个节点
Out[2]: []
复制代码
  从上面的例子中,我们似乎什么都看不到,那么我们来看下面的例子:
  In [3]: page.xpath(&#39;//li//img[1]&#39;)
Out[3]: [,
,
,
]
复制代码
  如您所见,我们选择了 4 个 img 节点。原因很简单,看下面的代码和解释就明白了:
  




(一)

(二)
(三)
总裁的新鲜小妻子



(四)

(五)
(六)
斗神天下


复制代码
  (一) 是第一个节点中的第一个节点
  节点。它的路径是 //
  (二) 是第一个节点的
  首先在节点
  节点。它的路径是/
  . (三) 没有被选中,因为它是标签下的第二个
  标签 (四) (五) (六)类似
  In [4]: page.xpath(&#39;//img[position()>1]&#39;)
Out[4]: [, ]
复制代码
  3.3 匹配未知节点
  当我们匹配时,会有一条不确定的路径。此时,我们将涉及匹配未知节点。匹配未知节点也有对应的语法,如下:
  通配符说明
  *
  匹配任何元素节点
  @*
  匹配任何属性节点
  匹配任意属性节点:
  In [1]: page.xpath(&#39;//li/a/*&#39;)
Out[1]: [,
,
,
]
复制代码
  匹配任何元素节点:
  In [2]: page.xpath(&#39;//li/a[@*]&#39;)
Out[2]: [,
,
,
]
复制代码
  3.4 获取节点中的文本
  可以通过attribute方法获取属性中的内容,但无法获取节点之间的内容。这时可以通过 text() 和 string() 方法获取其中的文本:
  使用 text() 获取节点中的文本:
  In [1]: page.xpath(&#39;//li/a[3]/text()&#39;)
Out[1]: [&#39;总裁的新鲜小妻子&#39;, &#39;斗神天下&#39;]
复制代码
  如您所见,标签之间的文本可以通过 text() 属性轻松获取。
  使用 string() 获取节点中的文本:
  In [1]: page.xpath(&#39;string(//li[1]/a[3])&#39;)
Out[1]: &#39;总裁的新鲜小妻子&#39;
复制代码
  3.5 选择多个路径
  有时我们需要同时查找多个条件。此时,您可以通过在路径表达式中使用竖线字符(“|”)来选择多个路径:
  In [1]: page.xpath(&#39;//li[1]/img[2]/@src | //li[1]/a[3]/text()&#39;)
Out[1]: [&#39;/kukuku/images/second.png&#39;, &#39;总裁的新鲜小妻子&#39;]
复制代码
  同时选择多条路径不会生成新的列表,只会生成一个列表,所以你需要考虑如何提取你返回的结果。一般来说,不建议使用多个条件进行搜索,因为将多个提取结果混合在一个列表中不利于提取。即使可以提取,也会增加计算量,降低程序性能。所以,尽量不要使用这种方法。
  下一条通知:
  Xpath用起来还是那么费劲,有没有其他更简单的方法?? ? 当然有,你可以用美味的汤完成你需要做的事情。敬请关注下一期 - BeautifulSoup:美味汤
  以上就是所有Xpath相关的内容了,可能没有其他的详细,但是对于你作为爬虫使用来说已经足够了。其实我也希望能详细一点,不过我是常客,个人不太喜欢用Xpath。如果你真的想深入了解 Xpth,我建议你去 W3C Xpath 教程 &gt;&gt;&gt; 看看他们是如何使用它的。
  好了,今天就到这里,我是康纳,一个从零开始的技术菜鸟。不知道你今天收获了多少?? ? 下次见!
  学习一时爽,学习永远爽!
  系列文章连接:
  Python爬虫十六种形式——第一种形式:HTTP协议&gt;&gt;&gt;
  Python爬虫十六式二:urllib和urllib3 &gt;&gt;&gt;
  Python爬虫十六式-第三式:Requests的用法&gt;&gt;&gt;
  Python爬虫十六-五:BeautifulSoup,美味的汤&gt;&gt;&gt;
  Python爬虫十六式六:JQuery的假兄弟-pyquery &gt;&gt;&gt;
  Python爬虫十六式七:正则美术&gt;&gt;&gt;
  Python爬虫十六式——第八式:实例分析——全书网&gt;&gt;&gt;
  转载于:

jquery抓取网页内容(从网页中准确提取所需的内容,你知道吗?)

网站优化优采云 发表了文章 • 0 个评论 • 56 次浏览 • 2022-04-07 13:01 • 来自相关话题

  jquery抓取网页内容(从网页中准确提取所需的内容,你知道吗?)
  1. 前言
  相信很多人在做开发的时候都有过这样的需求:准确的从网页中提取出需要的内容。想来想去,方法无外乎如下:(本人还是新手,有更好的方法,请指点)
  1. 使用正则表达式来匹配所需的元素。(缺点:如果同一类型的元素具有不同的属性,例如
  啊啊啊
  bbb
  , 如果要匹配所有的 div 元素,会比较麻烦,而且很容易得到不想要的结果而错过需要的结果。)
  2. 使用 Linq to XML 将网页转换为 XML 文档。(缺点:需要一个转换过程,效率不高。)
  3. 使用网站提供的WebServices或WebAPI等接口直接获取需要的数据。(缺点:需要先获取接口文档,一般不匿名提供。)
  随着近几年前端的兴起,越来越多的人开始认可和信服JQuery这个强大的工具。其中最重要的一点是JQuery选择器,简洁、高效、易学,大大提高了前端工程师的工作效率。. 想想看,提取网页内容就是在处理前端。如果可以使用 JQuery 选择器,那就完美了!!!
  2. 理论准备
  您想在.NET 下自己制作选择器吗?不,这不是我可以等待年轻一代去做的事情。. . . 既然 JQuery 已经存在,为什么不直接使用它的选择器呢?
  1. .NET 获取网页内容
  在这里您可以选择 webbrowser 控件。事实上,它是一个微型 IE,它可以做 IE 能做的所有事情。有人会问为什么不用WebClient直接下载网页内容呢?请看第二点。
  2. .NET 与 JS 交互
  使用webbrowser控件,不仅可以获得网页的内容,更重要的是提供了与网页交互的功能。使用内置的 Document 属性,我们可以将所需的 JS 代码注入网页并执行。
  3. 提取并返回所需内容
  在 .NET 中,我们可以使用 Docment 的 InvokeScript 函数来执行相应的 JS 函数并获取返回结果。
  现在理论已经准备好了,接下来让我们实现它。
  3. 函数实现
  测试页:(福利网站哦,不过绝对没有邪恶内容,请编辑明鉴!)
  功能要求:提取所有“好处”!!!!
  从图中可以看出,“福利”是准确提取出来的。而且您只能获得所需的属性值。您所要做的就是输入最短 15 个字符。
  我们看一下代码实现:
  其中wb为webbrowser控件,本节主要是将JQuery库注入到一些不收录JQuery库的网页中。
  无效的 InjectJQuery()
  {
  HtmlElement jquery = wb.Document.CreateElement("script");
  jquery.SetAttribute("src", "");
  wb.Document.Body.AppendChild(jquery);
  JQueryInjected = true;
  }
  这里是需要注入的JS函数。因为不同的需求有不同的代码,所以不能重复注入。当需求发生变化时,只需要更改注入的函数即可。
  JQScript = wb.Document.GetElementById("JQScript");
  如果(JQScript == null)
  {
  JQScript = wb.Document.CreateElement("script");
  JQScript.SetAttribute("id", "JQScript");
  JQScript.SetAttribute("type", "text/javascript");
  wb.Document.Body.AppendChild(JQScript);
  }
  这是关键代码,根据是否要提取属性生成不同的代码。注入的代码很简单,相信稍微懂一点前端的朋友一看就懂。而最后一行代码是执行注入的函数并获取返回值。
  if (txtAttribute.Text.Trim() == string.Empty)
  JQScript.SetAttribute("text", "function GetJQValue() { if ($('" + txtSelector.Text + "').length == 1) {" +
  "return $('" + txtSelector.Text + "')[0].outerHTML; }" +
  " else if ($('" + txtSelector.Text + "').length &gt; 1) {" +
  “var allhtml = '';” +
  " $('" + txtSelector.Text + "').each(function() {allhtml=allhtml+$(this)[0].outerHTML+'\\r\\n';});" +
  "返回所有html;}" +
  " else return '未找到项目。';}");
  别的
  {
  JQScript.SetAttribute("text", "function GetJQValue() { if ($('" + txtSelector.Text + "').length == 1) {" +
  "return $('" + txtSelector.Text + "').attr('" + txtAttribute.Text + "'); }" +
  " else if ($('" + txtSelector.Text + "').length &gt; 1) {" +
  “var allhtml = '';” +
  " $('" + txtSelector.Text + "').each(function() {allhtml=allhtml+$(this).attr('" + txtAttribute.Text + "')+'\\r\\n'; });" +
  "返回所有html;}" +
  " else return '未找到项目。';}");
  }
  textBox2.Text = wb.Document.InvokeScript("GetJQValue").ToString();
  相信大家一眼就看出来了。只需 10 行代码,您就可以使用强大的 JQuery 选择器。效率比旧方法高出许多倍。为什么不这样做? 查看全部

  jquery抓取网页内容(从网页中准确提取所需的内容,你知道吗?)
  1. 前言
  相信很多人在做开发的时候都有过这样的需求:准确的从网页中提取出需要的内容。想来想去,方法无外乎如下:(本人还是新手,有更好的方法,请指点)
  1. 使用正则表达式来匹配所需的元素。(缺点:如果同一类型的元素具有不同的属性,例如
  啊啊啊
  bbb
  , 如果要匹配所有的 div 元素,会比较麻烦,而且很容易得到不想要的结果而错过需要的结果。)
  2. 使用 Linq to XML 将网页转换为 XML 文档。(缺点:需要一个转换过程,效率不高。)
  3. 使用网站提供的WebServices或WebAPI等接口直接获取需要的数据。(缺点:需要先获取接口文档,一般不匿名提供。)
  随着近几年前端的兴起,越来越多的人开始认可和信服JQuery这个强大的工具。其中最重要的一点是JQuery选择器,简洁、高效、易学,大大提高了前端工程师的工作效率。. 想想看,提取网页内容就是在处理前端。如果可以使用 JQuery 选择器,那就完美了!!!
  2. 理论准备
  您想在.NET 下自己制作选择器吗?不,这不是我可以等待年轻一代去做的事情。. . . 既然 JQuery 已经存在,为什么不直接使用它的选择器呢?
  1. .NET 获取网页内容
  在这里您可以选择 webbrowser 控件。事实上,它是一个微型 IE,它可以做 IE 能做的所有事情。有人会问为什么不用WebClient直接下载网页内容呢?请看第二点。
  2. .NET 与 JS 交互
  使用webbrowser控件,不仅可以获得网页的内容,更重要的是提供了与网页交互的功能。使用内置的 Document 属性,我们可以将所需的 JS 代码注入网页并执行。
  3. 提取并返回所需内容
  在 .NET 中,我们可以使用 Docment 的 InvokeScript 函数来执行相应的 JS 函数并获取返回结果。
  现在理论已经准备好了,接下来让我们实现它。
  3. 函数实现
  测试页:(福利网站哦,不过绝对没有邪恶内容,请编辑明鉴!)
  功能要求:提取所有“好处”!!!!
  从图中可以看出,“福利”是准确提取出来的。而且您只能获得所需的属性值。您所要做的就是输入最短 15 个字符。
  我们看一下代码实现:
  其中wb为webbrowser控件,本节主要是将JQuery库注入到一些不收录JQuery库的网页中。
  无效的 InjectJQuery()
  {
  HtmlElement jquery = wb.Document.CreateElement("script");
  jquery.SetAttribute("src", "");
  wb.Document.Body.AppendChild(jquery);
  JQueryInjected = true;
  }
  这里是需要注入的JS函数。因为不同的需求有不同的代码,所以不能重复注入。当需求发生变化时,只需要更改注入的函数即可。
  JQScript = wb.Document.GetElementById("JQScript");
  如果(JQScript == null)
  {
  JQScript = wb.Document.CreateElement("script");
  JQScript.SetAttribute("id", "JQScript");
  JQScript.SetAttribute("type", "text/javascript");
  wb.Document.Body.AppendChild(JQScript);
  }
  这是关键代码,根据是否要提取属性生成不同的代码。注入的代码很简单,相信稍微懂一点前端的朋友一看就懂。而最后一行代码是执行注入的函数并获取返回值。
  if (txtAttribute.Text.Trim() == string.Empty)
  JQScript.SetAttribute("text", "function GetJQValue() { if ($('" + txtSelector.Text + "').length == 1) {" +
  "return $('" + txtSelector.Text + "')[0].outerHTML; }" +
  " else if ($('" + txtSelector.Text + "').length &gt; 1) {" +
  “var allhtml = '';” +
  " $('" + txtSelector.Text + "').each(function() {allhtml=allhtml+$(this)[0].outerHTML+'\\r\\n';});" +
  "返回所有html;}" +
  " else return '未找到项目。';}");
  别的
  {
  JQScript.SetAttribute("text", "function GetJQValue() { if ($('" + txtSelector.Text + "').length == 1) {" +
  "return $('" + txtSelector.Text + "').attr('" + txtAttribute.Text + "'); }" +
  " else if ($('" + txtSelector.Text + "').length &gt; 1) {" +
  “var allhtml = '';” +
  " $('" + txtSelector.Text + "').each(function() {allhtml=allhtml+$(this).attr('" + txtAttribute.Text + "')+'\\r\\n'; });" +
  "返回所有html;}" +
  " else return '未找到项目。';}");
  }
  textBox2.Text = wb.Document.InvokeScript("GetJQValue").ToString();
  相信大家一眼就看出来了。只需 10 行代码,您就可以使用强大的 JQuery 选择器。效率比旧方法高出许多倍。为什么不这样做?

jquery抓取网页内容(编写爬虫程序变的可能,实习操作起来非常的简单)

网站优化优采云 发表了文章 • 0 个评论 • 166 次浏览 • 2022-04-06 12:14 • 来自相关话题

  jquery抓取网页内容(编写爬虫程序变的可能,实习操作起来非常的简单)
  编写爬虫程序大多是后端开发者的工作,但是node的出现使得前端开发者编写爬虫程序成为可能,而且做法非常简单。
  我们首先介绍 SuperAgent,这是一个小型渐进式客户端 HTTP 请求库,其 API 与 Node.js 模块相同,具有许多高级 HTTP 客户端功能。从这个官方的解释可以看出,SuperAgent是一个实现http请求的库,封装在node环境中,实现对网页内容的请求。
  Cheerio 是在node 环境下,可以使用jquery api 之类的方法来获取网页的dom 中的数据。
  这两个工具结合起来抓取特定于业务的内容。我们都知道,在前端网页的开发中,经常会为样式相同的dom节点打上相同的类名,这样它们就可以具有相同的样式,这样就可以为我们在网页中抓取特定内容提供方便了。网页 。
  我们以某网站的消息为例:
  
  上图是新闻列表对应的代码。我们可以看到列表被包装在一个 id="xy-impcon" 的 div 容器中。每个分类的新闻列表使用ul,ul有一个通用的类名list-a。下面 ul 都有 li 标签和 a 标签。如果我们要获取每条新闻,可以使用cheerio来获取dom,可以写成$('#xy-impcon ul.list-a li a'),那么就写爬取链接和标题的程序,并将抓取数据保存到文件。
  var http = require("http"),
url = require("url"),
superagent = require("superagent"),
cheerio = require("cheerio"),
async = require("async"),
eventproxy = require('eventproxy');
var path = require('path');
var $ = require('jQuery');
var fs = require("fs");
var writerStream2 = fs.createWriteStream(path.resolve(__dirname,'../data/news.txt'),{ flags: 'w',encoding: null,mode: 0666 });
var text = [];
(function (){
superagent.get('爬取网站的url')
.end(function(err,pres){
var $ = cheerio.load(pres.text);
var curPageUrls = $('#xy-impcon ul.list-a li a');
console.log(curPageUrls.length)
curPageUrls.each(function(index, elem){
text.push({
title: $(elem).text(),
url: $(elem).attr('href')
})
})
writerStream2.write(JSON.stringify(text),'UTF8');
});
})();
  上面的代码将爬取的内容保存为文件。
  另外,我们还可以在node环境中使用phantomjs的网页模块,模拟浏览器端抓取网页数据,生成网页截图。具体用法后面会介绍 查看全部

  jquery抓取网页内容(编写爬虫程序变的可能,实习操作起来非常的简单)
  编写爬虫程序大多是后端开发者的工作,但是node的出现使得前端开发者编写爬虫程序成为可能,而且做法非常简单。
  我们首先介绍 SuperAgent,这是一个小型渐进式客户端 HTTP 请求库,其 API 与 Node.js 模块相同,具有许多高级 HTTP 客户端功能。从这个官方的解释可以看出,SuperAgent是一个实现http请求的库,封装在node环境中,实现对网页内容的请求。
  Cheerio 是在node 环境下,可以使用jquery api 之类的方法来获取网页的dom 中的数据。
  这两个工具结合起来抓取特定于业务的内容。我们都知道,在前端网页的开发中,经常会为样式相同的dom节点打上相同的类名,这样它们就可以具有相同的样式,这样就可以为我们在网页中抓取特定内容提供方便了。网页 。
  我们以某网站的消息为例:
  
  上图是新闻列表对应的代码。我们可以看到列表被包装在一个 id="xy-impcon" 的 div 容器中。每个分类的新闻列表使用ul,ul有一个通用的类名list-a。下面 ul 都有 li 标签和 a 标签。如果我们要获取每条新闻,可以使用cheerio来获取dom,可以写成$('#xy-impcon ul.list-a li a'),那么就写爬取链接和标题的程序,并将抓取数据保存到文件。
  var http = require("http"),
url = require("url"),
superagent = require("superagent"),
cheerio = require("cheerio"),
async = require("async"),
eventproxy = require('eventproxy');
var path = require('path');
var $ = require('jQuery');
var fs = require("fs");
var writerStream2 = fs.createWriteStream(path.resolve(__dirname,'../data/news.txt'),{ flags: 'w',encoding: null,mode: 0666 });
var text = [];
(function (){
superagent.get('爬取网站的url')
.end(function(err,pres){
var $ = cheerio.load(pres.text);
var curPageUrls = $('#xy-impcon ul.list-a li a');
console.log(curPageUrls.length)
curPageUrls.each(function(index, elem){
text.push({
title: $(elem).text(),
url: $(elem).attr('href')
})
})
writerStream2.write(JSON.stringify(text),'UTF8');
});
})();
  上面的代码将爬取的内容保存为文件。
  另外,我们还可以在node环境中使用phantomjs的网页模块,模拟浏览器端抓取网页数据,生成网页截图。具体用法后面会介绍

jquery抓取网页内容(使用selenium爬取动态网页信息Pythonselenium自动控制 )

网站优化优采云 发表了文章 • 0 个评论 • 54 次浏览 • 2022-04-04 23:29 • 来自相关话题

  jquery抓取网页内容(使用selenium爬取动态网页信息Pythonselenium自动控制
)
  使用selenium爬取动态网页信息
  python selenium自动控制浏览器抓取网页数据,包括按钮点击、页面跳转、搜索框输入、页面值数据存储、mongodb自动id识别等。
  首先介绍一下Python selenium——一个自动化测试工具,用来控制浏览器对网页的操作。当与爬虫中的 BeautifulSoup 结合使用时,它是无缝的。除了国外的一些异常验证页面,图片验证码我自己写了破解。图片验证码源码,成功率85%。
  使用 conda 管家安装:
  在cmd命令行输入“conda install selenium”进行安装
  还需要安装 Google Chrome Drive 或 Firefox 插件
  设置环境变量
  通过selenium访问百度
  from selenium import webdriver
#打开一个浏览器
browser = webdriver.Chrome()
#准备一个网址
url = 'http://www.baidu.com'
browser.get(url)
#获取元素
login = browser.find_elements_by_class_name('lb')[0]
print(login)
  获取网易云音乐
  
from selenium import webdriver
#打开浏览器
brower = webdriver.Chrome()
url='https://music.163.com/#/discover/toplist'
brower.get(url)
#寻找logo文字
#logo = brower.find_elements_by_class_name('logo')[0]
#print(logo.text)
#一般情况下动态加载的内容都可以找到
#有一种情况就没有
#就是网页内存在网页框架iframe
#需要切换网页的层级
#语法:brower.switch_to.frame(iframe的id或者你提前获取这个对象,放入此处)
#方法一:id
#brower.switch_to.frame('g_iframe')
#方法二:name
#brower.switch_to.frame('contentFrame')
#方法三:提前用变量存iframe
iframe = brower.find_element_by_id('g_iframe')
brower.switch_to.frame(iframe)
#寻找大容器
toplist = brower.find_element_by_id('toplist')
#寻找tbody 通过标签名
tbody = toplist.find_elements_by_tag_name('tbody')[0]
#寻找所有tr
trs = tbody.find_elements_by_tag_name('tr')
dataList = []
for each in trs:
#排名
rank = each.find_elements_by_tag_name('td')[0].find_elements_by_class_name('num')[0].text
musicName = each.find_elements_by_tag_name('td')[1].find_elements_by_class_name('txt')[0].\
find_element_by_tag_name('b').get_attribute('title')
#print(musicName)
singer = each.find_elements_by_tag_name('td')[3].find_elements_by_class_name('text')[0].\
get_attribute('title')
#print(singer)
dataList.append([rank,musicName,singer])
#print(dataList)
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.title = '云音乐飙升榜'
ws.append(['排名','歌名','歌手'])
for data in dataList:
ws.append(data)
wb.save("云音乐飙升榜.xlsx") 查看全部

  jquery抓取网页内容(使用selenium爬取动态网页信息Pythonselenium自动控制
)
  使用selenium爬取动态网页信息
  python selenium自动控制浏览器抓取网页数据,包括按钮点击、页面跳转、搜索框输入、页面值数据存储、mongodb自动id识别等。
  首先介绍一下Python selenium——一个自动化测试工具,用来控制浏览器对网页的操作。当与爬虫中的 BeautifulSoup 结合使用时,它是无缝的。除了国外的一些异常验证页面,图片验证码我自己写了破解。图片验证码源码,成功率85%。
  使用 conda 管家安装:
  在cmd命令行输入“conda install selenium”进行安装
  还需要安装 Google Chrome Drive 或 Firefox 插件
  设置环境变量
  通过selenium访问百度
  from selenium import webdriver
#打开一个浏览器
browser = webdriver.Chrome()
#准备一个网址
url = 'http://www.baidu.com'
browser.get(url)
#获取元素
login = browser.find_elements_by_class_name('lb')[0]
print(login)
  获取网易云音乐
  
from selenium import webdriver
#打开浏览器
brower = webdriver.Chrome()
url='https://music.163.com/#/discover/toplist'
brower.get(url)
#寻找logo文字
#logo = brower.find_elements_by_class_name('logo')[0]
#print(logo.text)
#一般情况下动态加载的内容都可以找到
#有一种情况就没有
#就是网页内存在网页框架iframe
#需要切换网页的层级
#语法:brower.switch_to.frame(iframe的id或者你提前获取这个对象,放入此处)
#方法一:id
#brower.switch_to.frame('g_iframe')
#方法二:name
#brower.switch_to.frame('contentFrame')
#方法三:提前用变量存iframe
iframe = brower.find_element_by_id('g_iframe')
brower.switch_to.frame(iframe)
#寻找大容器
toplist = brower.find_element_by_id('toplist')
#寻找tbody 通过标签名
tbody = toplist.find_elements_by_tag_name('tbody')[0]
#寻找所有tr
trs = tbody.find_elements_by_tag_name('tr')
dataList = []
for each in trs:
#排名
rank = each.find_elements_by_tag_name('td')[0].find_elements_by_class_name('num')[0].text
musicName = each.find_elements_by_tag_name('td')[1].find_elements_by_class_name('txt')[0].\
find_element_by_tag_name('b').get_attribute('title')
#print(musicName)
singer = each.find_elements_by_tag_name('td')[3].find_elements_by_class_name('text')[0].\
get_attribute('title')
#print(singer)
dataList.append([rank,musicName,singer])
#print(dataList)
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.title = '云音乐飙升榜'
ws.append(['排名','歌名','歌手'])
for data in dataList:
ws.append(data)
wb.save("云音乐飙升榜.xlsx")

jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)

网站优化优采云 发表了文章 • 0 个评论 • 53 次浏览 • 2022-04-04 05:11 • 来自相关话题

  jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)
  下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块。
  1. 正则表达式
  如果您是正则表达式的新手,或者需要一些提示,请查看正则表达式 HOWTO 以获得完整的介绍。
  当我们使用正则表达式抓取国家/地区数据时,我们首先尝试匹配元素的内容,如下所示:
  >>> import re
>>> import urllib2<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> re.findall(&#39;(.*?)&#39;, html)<br />
[&#39;/places/static/images/flags/gb.png&#39;, &#39;244,820 square kilometres&#39;, &#39;62,348,447&#39;, &#39;GB&#39;, &#39;United Kingdom&#39;, &#39;London&#39;, &#39;EU&#39;, &#39;.uk&#39;, &#39;GBP&#39;, &#39;Pound&#39;, &#39;44&#39;, &#39;@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA&#39;, &#39;^(([A-Z]\\d{2}[A-Z]{2})|([A-Z]\\d{3}[A-Z]{2})|([A-Z]{2}\\d{2}[A-Z]{2})|([A-Z]{2}\\d{3}[A-Z]{2})|([A-Z]\\d[A-Z]\\d[A-Z]{2})|([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})|(GIR0AA))$&#39;, &#39;en-GB,cy-GB,gd&#39;, &#39;IE &#39;]
>>>
  从以上结果可以看出,标签用于多个国家属性。要隔离 area 属性,我们只需选择其中的第二个元素,如下所示:
  >>> re.findall(&#39;(.*?)&#39;, html)[1]
&#39;244,820 square kilometres&#39;
  虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,该表已更改为删除第二行中的土地面积数据。如果我们现在只抓取数据,我们可以忽略这种未来可能发生的变化。但是,如果我们以后想再次获取这些数据,我们需要一个更健壮的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更加健壮,我们也可以添加它的父元素。由于元素具有 ID 属性,因此它应该是唯一的。
  >>> re.findall(&#39;Area: (.*?)&#39;, html)<br />
[&#39;244,820 square kilometres&#39;]
  这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在标签之间添加额外的空格,或者更改 area_label 等。下面是一个尝试支持这些可能性的改进版本。
  >>> re.findall(&#39;.*?(.*?)&#39;,html)[&#39;244,820 square kilometres&#39;]
  虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有一些细微的布局更改可能会使此正则表达式无法令人满意,例如为标签添加标题属性。
  从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。好在还有一些更好的解决方案,后面会介绍。
  2. 靓汤
  Beautiful Soup 是一个非常流行的 Python 模块。该模块可以解析网页并提供方便的界面来定位内容。如果您还没有安装该模块,可以使用以下命令安装其最新版本(需要先安装pip,请自行百度):
  pip install beautifulsoup4
  使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于大多数网页不是格式良好的 HTML,Beautiful Soup 需要确定它们的实际格式。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。
  <br />Area<br />Population<br />
  如果 Population 列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们在抓取时会得到错误的结果。让我们看看Beautiful Soup是如何处理它的。
  >>> from bs4 import BeautifulSoup
>>> broken_html = &#39;<br />AreaPopulation&#39;<br />
>>> # parse the HTML<br />
>>> soup = BeautifulSoup(broken_html, &#39;html.parser&#39;)<br />
>>> fixed_html = soup.prettify()<br />
>>> print fixed_html<br /><br /><br />
Area<br /><br />
Population<br /><br /><br />
  从上面的执行结果可以看出,Beautiful Soup 能够正确解析缺失的引号并关闭标签。现在我们可以使用 find() 和 find_all() 方法来定位我们需要的元素。
  >>> ul = soup.find(&#39;ul&#39;, attrs={&#39;class&#39;:&#39;country&#39;})<br />
>>> ul.find(&#39;li&#39;) # return just the first match<br />AreaPopulation<br />
>>> ul.find_all(&#39;li&#39;) # return all matches<br />
[AreaPopulation, Population]
  注意:由于不同版本的Python内置库的容错能力存在差异,处理结果可能与上述不同。详情请参阅: 。想知道所有的方法和参数,可以参考 Beautiful Soup 的官方文档
  以下是使用此方法提取样本国家地区数据的完整代码。
  >>> from bs4 import BeautifulSoup<br />>>> import urllib2<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> # locate the area row<br />>>> tr = soup.find(attrs={&#39;id&#39;:&#39;places_area__row&#39;})<br />>>> # locate the area tag<br />>>> td = tr.find(attrs={&#39;class&#39;:&#39;w2p_fw&#39;})<br />>>> area = td.text # extract the text from this tag<br />>>> print area<br />244,820 square kilometres
  此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局中的一些小变化,例如额外的空白和制表符属性,我们不再需要担心它了。
  3. Lxml
  Lxml 是基于 XML 解析库 libxml2 的 Python 包装器。模块用C语言编写,解析速度比Beautiful Soup快,但安装过程比较复杂。最新安装说明可以参考。**
  与 Beautiful Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。以下是使用此模块解析不完整 HTML 的示例:
  >>> import lxml.html<br />
>>> broken_html = &#39;<br />AreaPopulation&#39;
>>> # parse the HTML<br />
>>> tree = lxml.html.fromstring(broken_html)<br />
>>> fixed_html = lxml.html.tostring(tree, pretty_print=True)<br />
>>> print fixed_html<br /><br />Area<br />Population<br />
  同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。
  解析输入后,是时候选择元素了。此时,lxml 有几种不同的方法,例如 XPath 选择器和 Beautiful Soup 之类的 find() 方法。但是,我们将来会使用 CSS 选择器,因为它更简洁,可以在解析动态内容时重用。此外,一些有 jQuery 选择器经验的读者会更熟悉它。
  以下是使用 lxml 的 CSS 选择器提取区域数据的示例代码:
  >>> import urllib2<br />>>> import lxml.html<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> tree = lxml.html.fromstring(html)<br />>>> td = tree.cssselect(&#39;tr#places_area__row > td.w2p_fw&#39;)[0] # *行代码<br />>>> area = td.text_content()<br />>>> print area
244,820 square kilometres
  *行代码会先找到ID为places_area__row的表格行元素,然后选择类为w2p_fw的表格数据子标签。
  CSS 选择器表示用于选择元素的模式。以下是一些常用选择器的示例:
  选择所有标签: *<br />
选择 标签: a<br />
选择所有 class="link" 的元素: .link<br />
选择 class="link" 的 标签: a.link<br />
选择 id="home" 的 标签: a#home<br />
选择父元素为 标签的所有 子标签: a > span<br />
选择 标签内部的所有 标签: a span <br />
选择 title 属性为"Home"的所有 标签: a[title=Home]
  W3C 在
  Lxml 已经实现了大部分 CSS3 属性,其不支持的功能可以在: .
  注意:lxml 的内部实现实际上将 CSS 选择器转换为等效的 XPath 选择器。
  4. 性能比较
  在下面的代码中,每个爬虫会执行1000次,每次执行都会检查爬取结果是否正确,然后打印总时间。
  # -*- coding: utf-8 -*-<br /><br />import csv<br />import time<br />import urllib2<br />import re<br />import timeit<br />from bs4 import BeautifulSoup<br />import lxml.html<br /><br />
FIELDS = (&#39;area&#39;, &#39;population&#39;, &#39;iso&#39;, &#39;country&#39;, &#39;capital&#39;, &#39;continent&#39;, &#39;tld&#39;, &#39;currency_code&#39;, &#39;currency_name&#39;, &#39;phone&#39;, &#39;postal_code_format&#39;, &#39;postal_code_regex&#39;, &#39;languages&#39;, &#39;neighbours&#39;)<br /><br />def regex_scraper(html):<br /><br />
results = {}<br />for field in FIELDS:<br />
results[field] = re.search(&#39;.*?(.*?)&#39;.format(field), html).groups()[0]<br />return results<br /><br />def beautiful_soup_scraper(html):<br />
soup = BeautifulSoup(html, &#39;html.parser&#39;) <br />
results = {}<br />for field in FIELDS:<br />
results[field] = soup.find(&#39;table&#39;).find(&#39;tr&#39;, id=&#39;places_{}__row&#39;.format(field)).find(&#39;td&#39;, class_=&#39;w2p_fw&#39;).text<br />return results<br /><br />def lxml_scraper(html):<br />
tree = lxml.html.fromstring(html)<br />
results = {}<br />for field in FIELDS:<br />
results[field] = tree.cssselect(&#39;table > tr#places_{}__row > td.w2p_fw&#39;.format(field))[0].text_content()<br />return results<br /><br />def main():
times = {}
html = urllib2.urlopen(&#39;http://example.webscraping.com ... %2339;).read()<br />
NUM_ITERATIONS = 1000 # number of times to test each scraper<br />for name, scraper in (&#39;Regular expressions&#39;, regex_scraper), (&#39;Beautiful Soup&#39;, beautiful_soup_scraper), (&#39;Lxml&#39;, lxml_scraper):<br />
times[name] = []<br /># record start time of scrape<br />
start = time.time()<br />for i in range(NUM_ITERATIONS):<br />if scraper == regex_scraper:<br /># the regular expression module will cache results<br /># so need to purge this cache for meaningful timings<br />
re.purge() # *行代码<br />
result = scraper(html)<br /><br /># check scraped result is as expected<br />assert(result[&#39;area&#39;] == &#39;244,820 square kilometres&#39;)<br />
times[name].append(time.time() - start)<br /># record end time of scrape and output the total<br />
end = time.time()<br />print &#39;{}: {:.2f} seconds&#39;.format(name, end - start)<br /><br />
writer = csv.writer(open(&#39;times.csv&#39;, &#39;w&#39;))<br />
header = sorted(times.keys())<br />
writer.writerow(header)<br />for row in zip(*[times[scraper] for scraper in header]):<br />
writer.writerow(row)<br /><br />if __name__ == &#39;__main__&#39;:<br />
main()
  请注意,我们在 *line 代码中调用了 re.purge() 方法。默认情况下,正则表达式会缓存搜索结果,公平起见,我们需要使用这种方法来清除缓存。
  这是在我的计算机上运行脚本的结果:
  
  由于硬件条件的不同,不同计算机的执行结果也会有一定的差异。但是,每种方法之间的相对差异应该具有可比性。从结果可以看出,Beautiful Soup 在爬取我们的示例网页时比其他两种方法慢 7 倍以上。事实上,这个结果是意料之中的,因为 lxml 和正则表达式模块是用 C 编写的,而 Beautiful Soup 是用纯 Python 编写的。一个有趣的事实是 lxml 的性能与正则表达式差不多。由于 lxml 必须在搜索元素之前将输入解析为内部格式,因此会产生额外的开销。当爬取同一个网页的多个特征时,这个初始解析的开销会减少,lxml会更有竞争力,所以lxml是一个强大的模块。
  5. 总结
  三种网页抓取方式的优缺点:
  抓取方式 性能 使用难度 安装难度
  正则表达式
  快的
  困难
  简单(内置模块)
  美丽的汤
  慢
  简单的
  简单(纯 Python)
  lxml
  快的
  简单的
  比较困难
  如果您的爬虫的瓶颈是下载页面,而不是提取数据,那么使用较慢的方法(如 Beautiful Soup)不是问题。正则表达式在一次提取中非常有用,除了避免解析整个网页的开销之外,如果你只需要抓取少量数据并想避免额外的依赖,那么正则表达式可能更适合. 但是,总的来说,lxml 是抓取数据的最佳选择,因为它不仅速度更快,功能更强大,而正则表达式和 Beautiful Soup 仅在某些特定场景下才有用。 查看全部

  jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)
  下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块。
  1. 正则表达式
  如果您是正则表达式的新手,或者需要一些提示,请查看正则表达式 HOWTO 以获得完整的介绍。
  当我们使用正则表达式抓取国家/地区数据时,我们首先尝试匹配元素的内容,如下所示:
  >>> import re
>>> import urllib2<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> re.findall(&#39;(.*?)&#39;, html)<br />
[&#39;/places/static/images/flags/gb.png&#39;, &#39;244,820 square kilometres&#39;, &#39;62,348,447&#39;, &#39;GB&#39;, &#39;United Kingdom&#39;, &#39;London&#39;, &#39;EU&#39;, &#39;.uk&#39;, &#39;GBP&#39;, &#39;Pound&#39;, &#39;44&#39;, &#39;@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA&#39;, &#39;^(([A-Z]\\d{2}[A-Z]{2})|([A-Z]\\d{3}[A-Z]{2})|([A-Z]{2}\\d{2}[A-Z]{2})|([A-Z]{2}\\d{3}[A-Z]{2})|([A-Z]\\d[A-Z]\\d[A-Z]{2})|([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})|(GIR0AA))$&#39;, &#39;en-GB,cy-GB,gd&#39;, &#39;IE &#39;]
>>>
  从以上结果可以看出,标签用于多个国家属性。要隔离 area 属性,我们只需选择其中的第二个元素,如下所示:
  >>> re.findall(&#39;(.*?)&#39;, html)[1]
&#39;244,820 square kilometres&#39;
  虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,该表已更改为删除第二行中的土地面积数据。如果我们现在只抓取数据,我们可以忽略这种未来可能发生的变化。但是,如果我们以后想再次获取这些数据,我们需要一个更健壮的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更加健壮,我们也可以添加它的父元素。由于元素具有 ID 属性,因此它应该是唯一的。
  >>> re.findall(&#39;Area: (.*?)&#39;, html)<br />
[&#39;244,820 square kilometres&#39;]
  这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在标签之间添加额外的空格,或者更改 area_label 等。下面是一个尝试支持这些可能性的改进版本。
  >>> re.findall(&#39;.*?(.*?)&#39;,html)[&#39;244,820 square kilometres&#39;]
  虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有一些细微的布局更改可能会使此正则表达式无法令人满意,例如为标签添加标题属性。
  从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。好在还有一些更好的解决方案,后面会介绍。
  2. 靓汤
  Beautiful Soup 是一个非常流行的 Python 模块。该模块可以解析网页并提供方便的界面来定位内容。如果您还没有安装该模块,可以使用以下命令安装其最新版本(需要先安装pip,请自行百度):
  pip install beautifulsoup4
  使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于大多数网页不是格式良好的 HTML,Beautiful Soup 需要确定它们的实际格式。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。
  <br />Area<br />Population<br />
  如果 Population 列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们在抓取时会得到错误的结果。让我们看看Beautiful Soup是如何处理它的。
  >>> from bs4 import BeautifulSoup
>>> broken_html = &#39;<br />AreaPopulation&#39;<br />
>>> # parse the HTML<br />
>>> soup = BeautifulSoup(broken_html, &#39;html.parser&#39;)<br />
>>> fixed_html = soup.prettify()<br />
>>> print fixed_html<br /><br /><br />
Area<br /><br />
Population<br /><br /><br />
  从上面的执行结果可以看出,Beautiful Soup 能够正确解析缺失的引号并关闭标签。现在我们可以使用 find() 和 find_all() 方法来定位我们需要的元素。
  >>> ul = soup.find(&#39;ul&#39;, attrs={&#39;class&#39;:&#39;country&#39;})<br />
>>> ul.find(&#39;li&#39;) # return just the first match<br />AreaPopulation<br />
>>> ul.find_all(&#39;li&#39;) # return all matches<br />
[AreaPopulation, Population]
  注意:由于不同版本的Python内置库的容错能力存在差异,处理结果可能与上述不同。详情请参阅: 。想知道所有的方法和参数,可以参考 Beautiful Soup 的官方文档
  以下是使用此方法提取样本国家地区数据的完整代码。
  >>> from bs4 import BeautifulSoup<br />>>> import urllib2<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> # locate the area row<br />>>> tr = soup.find(attrs={&#39;id&#39;:&#39;places_area__row&#39;})<br />>>> # locate the area tag<br />>>> td = tr.find(attrs={&#39;class&#39;:&#39;w2p_fw&#39;})<br />>>> area = td.text # extract the text from this tag<br />>>> print area<br />244,820 square kilometres
  此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局中的一些小变化,例如额外的空白和制表符属性,我们不再需要担心它了。
  3. Lxml
  Lxml 是基于 XML 解析库 libxml2 的 Python 包装器。模块用C语言编写,解析速度比Beautiful Soup快,但安装过程比较复杂。最新安装说明可以参考。**
  与 Beautiful Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。以下是使用此模块解析不完整 HTML 的示例:
  >>> import lxml.html<br />
>>> broken_html = &#39;<br />AreaPopulation&#39;
>>> # parse the HTML<br />
>>> tree = lxml.html.fromstring(broken_html)<br />
>>> fixed_html = lxml.html.tostring(tree, pretty_print=True)<br />
>>> print fixed_html<br /><br />Area<br />Population<br />
  同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。
  解析输入后,是时候选择元素了。此时,lxml 有几种不同的方法,例如 XPath 选择器和 Beautiful Soup 之类的 find() 方法。但是,我们将来会使用 CSS 选择器,因为它更简洁,可以在解析动态内容时重用。此外,一些有 jQuery 选择器经验的读者会更熟悉它。
  以下是使用 lxml 的 CSS 选择器提取区域数据的示例代码:
  >>> import urllib2<br />>>> import lxml.html<br />>>> url = &#39;http://example.webscraping.com ... %3Bbr />>>> html = urllib2.urlopen(url).read()<br />>>> tree = lxml.html.fromstring(html)<br />>>> td = tree.cssselect(&#39;tr#places_area__row > td.w2p_fw&#39;)[0] # *行代码<br />>>> area = td.text_content()<br />>>> print area
244,820 square kilometres
  *行代码会先找到ID为places_area__row的表格行元素,然后选择类为w2p_fw的表格数据子标签。
  CSS 选择器表示用于选择元素的模式。以下是一些常用选择器的示例:
  选择所有标签: *<br />
选择 标签: a<br />
选择所有 class="link" 的元素: .link<br />
选择 class="link" 的 标签: a.link<br />
选择 id="home" 的 标签: a#home<br />
选择父元素为 标签的所有 子标签: a > span<br />
选择 标签内部的所有 标签: a span <br />
选择 title 属性为"Home"的所有 标签: a[title=Home]
  W3C 在
  Lxml 已经实现了大部分 CSS3 属性,其不支持的功能可以在: .
  注意:lxml 的内部实现实际上将 CSS 选择器转换为等效的 XPath 选择器。
  4. 性能比较
  在下面的代码中,每个爬虫会执行1000次,每次执行都会检查爬取结果是否正确,然后打印总时间。
  # -*- coding: utf-8 -*-<br /><br />import csv<br />import time<br />import urllib2<br />import re<br />import timeit<br />from bs4 import BeautifulSoup<br />import lxml.html<br /><br />
FIELDS = (&#39;area&#39;, &#39;population&#39;, &#39;iso&#39;, &#39;country&#39;, &#39;capital&#39;, &#39;continent&#39;, &#39;tld&#39;, &#39;currency_code&#39;, &#39;currency_name&#39;, &#39;phone&#39;, &#39;postal_code_format&#39;, &#39;postal_code_regex&#39;, &#39;languages&#39;, &#39;neighbours&#39;)<br /><br />def regex_scraper(html):<br /><br />
results = {}<br />for field in FIELDS:<br />
results[field] = re.search(&#39;.*?(.*?)&#39;.format(field), html).groups()[0]<br />return results<br /><br />def beautiful_soup_scraper(html):<br />
soup = BeautifulSoup(html, &#39;html.parser&#39;) <br />
results = {}<br />for field in FIELDS:<br />
results[field] = soup.find(&#39;table&#39;).find(&#39;tr&#39;, id=&#39;places_{}__row&#39;.format(field)).find(&#39;td&#39;, class_=&#39;w2p_fw&#39;).text<br />return results<br /><br />def lxml_scraper(html):<br />
tree = lxml.html.fromstring(html)<br />
results = {}<br />for field in FIELDS:<br />
results[field] = tree.cssselect(&#39;table > tr#places_{}__row > td.w2p_fw&#39;.format(field))[0].text_content()<br />return results<br /><br />def main():
times = {}
html = urllib2.urlopen(&#39;http://example.webscraping.com ... %2339;).read()<br />
NUM_ITERATIONS = 1000 # number of times to test each scraper<br />for name, scraper in (&#39;Regular expressions&#39;, regex_scraper), (&#39;Beautiful Soup&#39;, beautiful_soup_scraper), (&#39;Lxml&#39;, lxml_scraper):<br />
times[name] = []<br /># record start time of scrape<br />
start = time.time()<br />for i in range(NUM_ITERATIONS):<br />if scraper == regex_scraper:<br /># the regular expression module will cache results<br /># so need to purge this cache for meaningful timings<br />
re.purge() # *行代码<br />
result = scraper(html)<br /><br /># check scraped result is as expected<br />assert(result[&#39;area&#39;] == &#39;244,820 square kilometres&#39;)<br />
times[name].append(time.time() - start)<br /># record end time of scrape and output the total<br />
end = time.time()<br />print &#39;{}: {:.2f} seconds&#39;.format(name, end - start)<br /><br />
writer = csv.writer(open(&#39;times.csv&#39;, &#39;w&#39;))<br />
header = sorted(times.keys())<br />
writer.writerow(header)<br />for row in zip(*[times[scraper] for scraper in header]):<br />
writer.writerow(row)<br /><br />if __name__ == &#39;__main__&#39;:<br />
main()
  请注意,我们在 *line 代码中调用了 re.purge() 方法。默认情况下,正则表达式会缓存搜索结果,公平起见,我们需要使用这种方法来清除缓存。
  这是在我的计算机上运行脚本的结果:
  
  由于硬件条件的不同,不同计算机的执行结果也会有一定的差异。但是,每种方法之间的相对差异应该具有可比性。从结果可以看出,Beautiful Soup 在爬取我们的示例网页时比其他两种方法慢 7 倍以上。事实上,这个结果是意料之中的,因为 lxml 和正则表达式模块是用 C 编写的,而 Beautiful Soup 是用纯 Python 编写的。一个有趣的事实是 lxml 的性能与正则表达式差不多。由于 lxml 必须在搜索元素之前将输入解析为内部格式,因此会产生额外的开销。当爬取同一个网页的多个特征时,这个初始解析的开销会减少,lxml会更有竞争力,所以lxml是一个强大的模块。
  5. 总结
  三种网页抓取方式的优缺点:
  抓取方式 性能 使用难度 安装难度
  正则表达式
  快的
  困难
  简单(内置模块)
  美丽的汤
  慢
  简单的
  简单(纯 Python)
  lxml
  快的
  简单的
  比较困难
  如果您的爬虫的瓶颈是下载页面,而不是提取数据,那么使用较慢的方法(如 Beautiful Soup)不是问题。正则表达式在一次提取中非常有用,除了避免解析整个网页的开销之外,如果你只需要抓取少量数据并想避免额外的依赖,那么正则表达式可能更适合. 但是,总的来说,lxml 是抓取数据的最佳选择,因为它不仅速度更快,功能更强大,而正则表达式和 Beautiful Soup 仅在某些特定场景下才有用。

jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)

网站优化优采云 发表了文章 • 0 个评论 • 385 次浏览 • 2022-04-03 03:07 • 来自相关话题

  jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)
  下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块。
  1. 正则表达式
  如果您是正则表达式的新手,或者需要一些提示,请查看正则表达式 HOWTO 以获得完整的介绍。
  当我们使用正则表达式抓取国家/地区数据时,我们首先尝试匹配元素的内容,如下所示:
  >>> import re
>>> import urllib2
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> re.findall(&#39;(.*?)&#39;, html)
[&#39;/places/static/images/flags/gb.png&#39;, &#39;244,820 square kilometres&#39;, &#39;62,348,447&#39;, &#39;GB&#39;, &#39;United Kingdom&#39;, &#39;London&#39;, &#39;EU&#39;, &#39;.uk&#39;, &#39;GBP&#39;, &#39;Pound&#39;, &#39;44&#39;, &#39;@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA&#39;, &#39;^(([A-Z]\\d{2}[A-Z]{2})|([A-Z]\\d{3}[A-Z]{2})|([A-Z]{2}\\d{2}[A-Z]{2})|([A-Z]{2}\\d{3}[A-Z]{2})|([A-Z]\\d[A-Z]\\d[A-Z]{2})|([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})|(GIR0AA))$&#39;, &#39;en-GB,cy-GB,gd&#39;, &#39;IE &#39;]
>>>
  从以上结果可以看出,标签用于多个国家属性。要隔离 area 属性,我们只需选择其中的第二个元素,如下所示:
  >>> re.findall(&#39;(.*?)&#39;, html)[1]
&#39;244,820 square kilometres&#39;
  虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,该表已更改为删除第二行中的土地面积数据。如果我们现在只抓取数据,我们可以忽略这种未来可能发生的变化。但是,如果我们以后想再次获取这些数据,我们需要一个更健壮的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更加健壮,我们也可以添加它的父元素。由于元素具有 ID 属性,因此它应该是唯一的。
  >>> re.findall(&#39;Area: (.*?)&#39;, html)
[&#39;244,820 square kilometres&#39;]
  这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在标签之间添加额外的空格,或者更改 area_label 等。下面是一个改进版本,试图支持这些可能性。
  >>> re.findall(&#39;.*?(.*?)&#39;,html)[&#39;244,820 square kilometres&#39;]
  虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有一些细微的布局更改可能会使此正则表达式无法令人满意,例如为标签添加标题属性。
  从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。好在还有一些更好的解决方案,后面会介绍。
  2. 靓汤
  Beautiful Soup 是一个非常流行的 Python 模块。该模块可以解析网页并提供方便的界面来定位内容。如果您还没有安装该模块,可以使用以下命令安装其最新版本(需要先安装pip,请自行百度):
  pip install beautifulsoup4
  使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于大多数网页不是格式良好的 HTML,Beautiful Soup 需要确定它们的实际格式。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。
  
Area
Population
  如果 Population 列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们在抓取时会得到错误的结果。让我们看看Beautiful Soup是如何处理它的。
  >>> from bs4 import BeautifulSoup
>>> broken_html = &#39;AreaPopulation&#39;
>>> # parse the HTML
>>> soup = BeautifulSoup(broken_html, &#39;html.parser&#39;)
>>> fixed_html = soup.prettify()
>>> print fixed_html

Area

Population


  从上面的执行结果可以看出,Beautiful Soup 能够正确解析缺失的引号并关闭标签。现在我们可以使用 find() 和 find_all() 方法来定位我们需要的元素。
  >>> ul = soup.find(&#39;ul&#39;, attrs={&#39;class&#39;:&#39;country&#39;})
>>> ul.find(&#39;li&#39;) # return just the first match
AreaPopulation
>>> ul.find_all(&#39;li&#39;) # return all matches
[AreaPopulation, Population]
  注意:由于不同版本的Python内置库容错能力不同,处理结果可能与上述不同。详情请参阅: 。想知道所有的方法和参数,可以参考 Beautiful Soup 的官方文档
  以下是使用此方法提取样本国家地区数据的完整代码。
  >>> from bs4 import BeautifulSoup
>>> import urllib2
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> # locate the area row
>>> tr = soup.find(attrs={&#39;id&#39;:&#39;places_area__row&#39;})
>>> # locate the area tag
>>> td = tr.find(attrs={&#39;class&#39;:&#39;w2p_fw&#39;})
>>> area = td.text # extract the text from this tag
>>> print area
244,820 square kilometres
  此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局中的一些小变化,例如额外的空白和制表符属性,我们不再需要担心它了。
  3. Lxml
  Lxml 是基于 XML 解析库 libxml2 的 Python 包装器。模块用C语言编写,解析速度比Beautiful Soup快,但安装过程比较复杂。最新安装说明可以参考。**
  与 Beautiful Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。以下是使用此模块解析不完整 HTML 的示例:
  >>> import lxml.html
>>> broken_html = &#39;AreaPopulation&#39;
>>> # parse the HTML
>>> tree = lxml.html.fromstring(broken_html)
>>> fixed_html = lxml.html.tostring(tree, pretty_print=True)
>>> print fixed_html
Area
Population
  同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。
  解析输入后,是时候选择元素了。此时,lxml 有几种不同的方法,例如 XPath 选择器和 Beautiful Soup 之类的 find() 方法。但是,我们将来会使用 CSS 选择器,因为它更简洁,可以在解析动态内容时重用。此外,一些有 jQuery 选择器经验的读者会更熟悉它。
  以下是使用 lxml 的 CSS 选择器提取区域数据的示例代码:
  >>> import urllib2
>>> import lxml.html
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> tree = lxml.html.fromstring(html)
>>> td = tree.cssselect(&#39;tr#places_area__row > td.w2p_fw&#39;)[0] # *行代码
>>> area = td.text_content()
>>> print area
244,820 square kilometres
  *行代码会先找到ID为places_area__row的表格行元素,然后选择类为w2p_fw的表格数据子标签。
  CSS 选择器表示用于选择元素的模式。以下是一些常用选择器的示例:
  选择所有标签: *
选择 标签: a
选择所有 class="link" 的元素: .link
选择 class="link" 的 标签: a.link
选择 id="home" 的 标签: a#home
选择父元素为 标签的所有 子标签: a > span
选择 标签内部的所有 标签: a span
选择 title 属性为"Home"的所有 标签: a[title=Home]
  W3C 在
  Lxml 已经实现了大部分 CSS3 属性,其不支持的功能可以在: .
  注意:lxml 的内部实现实际上将 CSS 选择器转换为等效的 XPath 选择器。
  4. 性能比较
  在下面的代码中,每个爬虫会执行1000次,每次执行都会检查爬取结果是否正确,然后打印总时间。
  # -*- coding: utf-8 -*-
import csv
import time
import urllib2
import re
import timeit
from bs4 import BeautifulSoup
import lxml.html
FIELDS = (&#39;area&#39;, &#39;population&#39;, &#39;iso&#39;, &#39;country&#39;, &#39;capital&#39;, &#39;continent&#39;, &#39;tld&#39;, &#39;currency_code&#39;, &#39;currency_name&#39;, &#39;phone&#39;, &#39;postal_code_format&#39;, &#39;postal_code_regex&#39;, &#39;languages&#39;, &#39;neighbours&#39;)
def regex_scraper(html):
results = {}
for field in FIELDS:
results[field] = re.search(&#39;.*?(.*?)&#39;.format(field), html).groups()[0]
return results
def beautiful_soup_scraper(html):
soup = BeautifulSoup(html, &#39;html.parser&#39;)
results = {}
for field in FIELDS:
results[field] = soup.find(&#39;table&#39;).find(&#39;tr&#39;, id=&#39;places_{}__row&#39;.format(field)).find(&#39;td&#39;, class_=&#39;w2p_fw&#39;).text
return results
def lxml_scraper(html):
tree = lxml.html.fromstring(html)
results = {}
for field in FIELDS:
results[field] = tree.cssselect(&#39;table > tr#places_{}__row > td.w2p_fw&#39;.format(field))[0].text_content()
return results
def main():
times = {}
html = urllib2.urlopen(&#39;http://example.webscraping.com ... %2339;).read()
NUM_ITERATIONS = 1000 # number of times to test each scraper
for name, scraper in (&#39;Regular expressions&#39;, regex_scraper), (&#39;Beautiful Soup&#39;, beautiful_soup_scraper), (&#39;Lxml&#39;, lxml_scraper):
times[name] = []
# record start time of scrape
start = time.time()
for i in range(NUM_ITERATIONS):
if scraper == regex_scraper:
# the regular expression module will cache results
# so need to purge this cache for meaningful timings
re.purge() # *行代码
result = scraper(html)
# check scraped result is as expected
assert(result[&#39;area&#39;] == &#39;244,820 square kilometres&#39;)
times[name].append(time.time() - start)
# record end time of scrape and output the total
end = time.time()
print &#39;{}: {:.2f} seconds&#39;.format(name, end - start)
writer = csv.writer(open(&#39;times.csv&#39;, &#39;w&#39;))
header = sorted(times.keys())
writer.writerow(header)
for row in zip(*[times[scraper] for scraper in header]):
writer.writerow(row)
if __name__ == &#39;__main__&#39;:
main()
  请注意,我们在 *line 代码中调用了 re.purge() 方法。默认情况下,正则表达式会缓存搜索结果,公平起见,我们需要使用这种方法来清除缓存。
  这是在我的计算机上运行脚本的结果:
  
  由于硬件条件的不同,不同计算机的执行结果也会有一定的差异。但是,每种方法之间的相对差异应该具有可比性。从结果可以看出,Beautiful Soup 在爬取我们的示例网页时比其他两种方法慢 7 倍以上。事实上,这个结果是意料之中的,因为 lxml 和正则表达式模块是用 C 编写的,而 Beautiful Soup 是用纯 Python 编写的。一个有趣的事实是 lxml 的性能与正则表达式差不多。由于 lxml 必须在搜索元素之前将输入解析为内部格式,因此会产生额外的开销。当爬取同一个网页的多个特征时,这个初始解析的开销会减少,lxml会更有竞争力,所以lxml是一个强大的模块。
  5. 总结
  三种网页抓取方式的优缺点:
  抓取方式 性能 使用难度 安装难度
  正则表达式
  快的
  困难
  简单(内置模块)
  美丽的汤
  慢
  简单的
  简单(纯 Python)
  lxml
  快的
  简单的
  比较困难
  如果您的爬虫的瓶颈是下载页面,而不是提取数据,那么使用较慢的方法(如 Beautiful Soup)不是问题。正则表达式在一次提取中非常有用,除了避免解析整个网页的开销之外,如果你只需要抓取少量数据并想避免额外的依赖,那么正则表达式可能更适合. 但是,一般来说,lxml 是抓取数据的最佳选择,因为它不仅速度更快,功能更强大,而正则表达式和 Beautiful Soup 仅在某些特定场景下才有用。 查看全部

  jquery抓取网页内容(三种抓取网页数据的方法-2.Beautiful)
  下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块。
  1. 正则表达式
  如果您是正则表达式的新手,或者需要一些提示,请查看正则表达式 HOWTO 以获得完整的介绍。
  当我们使用正则表达式抓取国家/地区数据时,我们首先尝试匹配元素的内容,如下所示:
  >>> import re
>>> import urllib2
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> re.findall(&#39;(.*?)&#39;, html)
[&#39;/places/static/images/flags/gb.png&#39;, &#39;244,820 square kilometres&#39;, &#39;62,348,447&#39;, &#39;GB&#39;, &#39;United Kingdom&#39;, &#39;London&#39;, &#39;EU&#39;, &#39;.uk&#39;, &#39;GBP&#39;, &#39;Pound&#39;, &#39;44&#39;, &#39;@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA&#39;, &#39;^(([A-Z]\\d{2}[A-Z]{2})|([A-Z]\\d{3}[A-Z]{2})|([A-Z]{2}\\d{2}[A-Z]{2})|([A-Z]{2}\\d{3}[A-Z]{2})|([A-Z]\\d[A-Z]\\d[A-Z]{2})|([A-Z]{2}\\d[A-Z]\\d[A-Z]{2})|(GIR0AA))$&#39;, &#39;en-GB,cy-GB,gd&#39;, &#39;IE &#39;]
>>>
  从以上结果可以看出,标签用于多个国家属性。要隔离 area 属性,我们只需选择其中的第二个元素,如下所示:
  >>> re.findall(&#39;(.*?)&#39;, html)[1]
&#39;244,820 square kilometres&#39;
  虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,该表已更改为删除第二行中的土地面积数据。如果我们现在只抓取数据,我们可以忽略这种未来可能发生的变化。但是,如果我们以后想再次获取这些数据,我们需要一个更健壮的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更加健壮,我们也可以添加它的父元素。由于元素具有 ID 属性,因此它应该是唯一的。
  >>> re.findall(&#39;Area: (.*?)&#39;, html)
[&#39;244,820 square kilometres&#39;]
  这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在标签之间添加额外的空格,或者更改 area_label 等。下面是一个改进版本,试图支持这些可能性。
  >>> re.findall(&#39;.*?(.*?)&#39;,html)[&#39;244,820 square kilometres&#39;]
  虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有一些细微的布局更改可能会使此正则表达式无法令人满意,例如为标签添加标题属性。
  从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。好在还有一些更好的解决方案,后面会介绍。
  2. 靓汤
  Beautiful Soup 是一个非常流行的 Python 模块。该模块可以解析网页并提供方便的界面来定位内容。如果您还没有安装该模块,可以使用以下命令安装其最新版本(需要先安装pip,请自行百度):
  pip install beautifulsoup4
  使用 Beautiful Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于大多数网页不是格式良好的 HTML,Beautiful Soup 需要确定它们的实际格式。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。
  
Area
Population
  如果 Population 列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们在抓取时会得到错误的结果。让我们看看Beautiful Soup是如何处理它的。
  >>> from bs4 import BeautifulSoup
>>> broken_html = &#39;AreaPopulation&#39;
>>> # parse the HTML
>>> soup = BeautifulSoup(broken_html, &#39;html.parser&#39;)
>>> fixed_html = soup.prettify()
>>> print fixed_html

Area

Population


  从上面的执行结果可以看出,Beautiful Soup 能够正确解析缺失的引号并关闭标签。现在我们可以使用 find() 和 find_all() 方法来定位我们需要的元素。
  >>> ul = soup.find(&#39;ul&#39;, attrs={&#39;class&#39;:&#39;country&#39;})
>>> ul.find(&#39;li&#39;) # return just the first match
AreaPopulation
>>> ul.find_all(&#39;li&#39;) # return all matches
[AreaPopulation, Population]
  注意:由于不同版本的Python内置库容错能力不同,处理结果可能与上述不同。详情请参阅: 。想知道所有的方法和参数,可以参考 Beautiful Soup 的官方文档
  以下是使用此方法提取样本国家地区数据的完整代码。
  >>> from bs4 import BeautifulSoup
>>> import urllib2
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> # locate the area row
>>> tr = soup.find(attrs={&#39;id&#39;:&#39;places_area__row&#39;})
>>> # locate the area tag
>>> td = tr.find(attrs={&#39;class&#39;:&#39;w2p_fw&#39;})
>>> area = td.text # extract the text from this tag
>>> print area
244,820 square kilometres
  此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局中的一些小变化,例如额外的空白和制表符属性,我们不再需要担心它了。
  3. Lxml
  Lxml 是基于 XML 解析库 libxml2 的 Python 包装器。模块用C语言编写,解析速度比Beautiful Soup快,但安装过程比较复杂。最新安装说明可以参考。**
  与 Beautiful Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。以下是使用此模块解析不完整 HTML 的示例:
  >>> import lxml.html
>>> broken_html = &#39;AreaPopulation&#39;
>>> # parse the HTML
>>> tree = lxml.html.fromstring(broken_html)
>>> fixed_html = lxml.html.tostring(tree, pretty_print=True)
>>> print fixed_html
Area
Population
  同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。
  解析输入后,是时候选择元素了。此时,lxml 有几种不同的方法,例如 XPath 选择器和 Beautiful Soup 之类的 find() 方法。但是,我们将来会使用 CSS 选择器,因为它更简洁,可以在解析动态内容时重用。此外,一些有 jQuery 选择器经验的读者会更熟悉它。
  以下是使用 lxml 的 CSS 选择器提取区域数据的示例代码:
  >>> import urllib2
>>> import lxml.html
>>> url = &#39;http://example.webscraping.com ... 39%3B
>>> html = urllib2.urlopen(url).read()
>>> tree = lxml.html.fromstring(html)
>>> td = tree.cssselect(&#39;tr#places_area__row > td.w2p_fw&#39;)[0] # *行代码
>>> area = td.text_content()
>>> print area
244,820 square kilometres
  *行代码会先找到ID为places_area__row的表格行元素,然后选择类为w2p_fw的表格数据子标签。
  CSS 选择器表示用于选择元素的模式。以下是一些常用选择器的示例:
  选择所有标签: *
选择 标签: a
选择所有 class="link" 的元素: .link
选择 class="link" 的 标签: a.link
选择 id="home" 的 标签: a#home
选择父元素为 标签的所有 子标签: a > span
选择 标签内部的所有 标签: a span
选择 title 属性为"Home"的所有 标签: a[title=Home]
  W3C 在
  Lxml 已经实现了大部分 CSS3 属性,其不支持的功能可以在: .
  注意:lxml 的内部实现实际上将 CSS 选择器转换为等效的 XPath 选择器。
  4. 性能比较
  在下面的代码中,每个爬虫会执行1000次,每次执行都会检查爬取结果是否正确,然后打印总时间。
  # -*- coding: utf-8 -*-
import csv
import time
import urllib2
import re
import timeit
from bs4 import BeautifulSoup
import lxml.html
FIELDS = (&#39;area&#39;, &#39;population&#39;, &#39;iso&#39;, &#39;country&#39;, &#39;capital&#39;, &#39;continent&#39;, &#39;tld&#39;, &#39;currency_code&#39;, &#39;currency_name&#39;, &#39;phone&#39;, &#39;postal_code_format&#39;, &#39;postal_code_regex&#39;, &#39;languages&#39;, &#39;neighbours&#39;)
def regex_scraper(html):
results = {}
for field in FIELDS:
results[field] = re.search(&#39;.*?(.*?)&#39;.format(field), html).groups()[0]
return results
def beautiful_soup_scraper(html):
soup = BeautifulSoup(html, &#39;html.parser&#39;)
results = {}
for field in FIELDS:
results[field] = soup.find(&#39;table&#39;).find(&#39;tr&#39;, id=&#39;places_{}__row&#39;.format(field)).find(&#39;td&#39;, class_=&#39;w2p_fw&#39;).text
return results
def lxml_scraper(html):
tree = lxml.html.fromstring(html)
results = {}
for field in FIELDS:
results[field] = tree.cssselect(&#39;table > tr#places_{}__row > td.w2p_fw&#39;.format(field))[0].text_content()
return results
def main():
times = {}
html = urllib2.urlopen(&#39;http://example.webscraping.com ... %2339;).read()
NUM_ITERATIONS = 1000 # number of times to test each scraper
for name, scraper in (&#39;Regular expressions&#39;, regex_scraper), (&#39;Beautiful Soup&#39;, beautiful_soup_scraper), (&#39;Lxml&#39;, lxml_scraper):
times[name] = []
# record start time of scrape
start = time.time()
for i in range(NUM_ITERATIONS):
if scraper == regex_scraper:
# the regular expression module will cache results
# so need to purge this cache for meaningful timings
re.purge() # *行代码
result = scraper(html)
# check scraped result is as expected
assert(result[&#39;area&#39;] == &#39;244,820 square kilometres&#39;)
times[name].append(time.time() - start)
# record end time of scrape and output the total
end = time.time()
print &#39;{}: {:.2f} seconds&#39;.format(name, end - start)
writer = csv.writer(open(&#39;times.csv&#39;, &#39;w&#39;))
header = sorted(times.keys())
writer.writerow(header)
for row in zip(*[times[scraper] for scraper in header]):
writer.writerow(row)
if __name__ == &#39;__main__&#39;:
main()
  请注意,我们在 *line 代码中调用了 re.purge() 方法。默认情况下,正则表达式会缓存搜索结果,公平起见,我们需要使用这种方法来清除缓存。
  这是在我的计算机上运行脚本的结果:
  
  由于硬件条件的不同,不同计算机的执行结果也会有一定的差异。但是,每种方法之间的相对差异应该具有可比性。从结果可以看出,Beautiful Soup 在爬取我们的示例网页时比其他两种方法慢 7 倍以上。事实上,这个结果是意料之中的,因为 lxml 和正则表达式模块是用 C 编写的,而 Beautiful Soup 是用纯 Python 编写的。一个有趣的事实是 lxml 的性能与正则表达式差不多。由于 lxml 必须在搜索元素之前将输入解析为内部格式,因此会产生额外的开销。当爬取同一个网页的多个特征时,这个初始解析的开销会减少,lxml会更有竞争力,所以lxml是一个强大的模块。
  5. 总结
  三种网页抓取方式的优缺点:
  抓取方式 性能 使用难度 安装难度
  正则表达式
  快的
  困难
  简单(内置模块)
  美丽的汤
  慢
  简单的
  简单(纯 Python)
  lxml
  快的
  简单的
  比较困难
  如果您的爬虫的瓶颈是下载页面,而不是提取数据,那么使用较慢的方法(如 Beautiful Soup)不是问题。正则表达式在一次提取中非常有用,除了避免解析整个网页的开销之外,如果你只需要抓取少量数据并想避免额外的依赖,那么正则表达式可能更适合. 但是,一般来说,lxml 是抓取数据的最佳选择,因为它不仅速度更快,功能更强大,而正则表达式和 Beautiful Soup 仅在某些特定场景下才有用。

jquery抓取网页内容(jquery抓取网页内容很简单,具体可以用session模拟登录网页)

网站优化优采云 发表了文章 • 0 个评论 • 105 次浏览 • 2022-04-02 16:04 • 来自相关话题

  jquery抓取网页内容(jquery抓取网页内容很简单,具体可以用session模拟登录网页)
  jquery抓取网页内容很简单,具体可以用session模拟登录网页,在浏览器里输入图片地址,这样就会跳转到电商网站,并且显示该图片,然后再用另一套代码把网页内容显示出来,下面是以网页源码为例。首先在userdata_loader中加入canvasimgdataimg-id:canvas-idimg_cookie:cookieusername:admin然后重定向到首页,看图中间红色框框。
  接下来在canvas中加入canvas的animation,设置好该animation长度(方便到时渲染),双击某个loader,就会从浏览器扩展中得到一个img对象。接下来在loader中加入ts代码。方法很简单,只需要将canvas放到loader中即可。接下来就是加载图片即可。就我目前所用的项目,图片加载速度大概在12ms左右,已经能满足要求。
  应该可以。jquerysetoncontainer的animation是最合适的。另外就是尽量少用requestanimationframe等惰性方法,尽量用throttle,不然每一帧获取网络动画都很耗时。
  用ajax去请求图片,然后保存到一个图片,用loader渲染,
  1.加载图片2.利用js,
  看看这个,反正我是这么做的,确保它会在页面中等待解析ie==0/10ie6/9/11ie11/12(mozilla/5.0(windowsnt10.0;win64;x64)applewebkit/537.36(khtml,likegecko)chrome/73.0.3686.0safari/537.36等待等待一段时间保存图片。等待有时间了再解析返回结果。 查看全部

  jquery抓取网页内容(jquery抓取网页内容很简单,具体可以用session模拟登录网页)
  jquery抓取网页内容很简单,具体可以用session模拟登录网页,在浏览器里输入图片地址,这样就会跳转到电商网站,并且显示该图片,然后再用另一套代码把网页内容显示出来,下面是以网页源码为例。首先在userdata_loader中加入canvasimgdataimg-id:canvas-idimg_cookie:cookieusername:admin然后重定向到首页,看图中间红色框框。
  接下来在canvas中加入canvas的animation,设置好该animation长度(方便到时渲染),双击某个loader,就会从浏览器扩展中得到一个img对象。接下来在loader中加入ts代码。方法很简单,只需要将canvas放到loader中即可。接下来就是加载图片即可。就我目前所用的项目,图片加载速度大概在12ms左右,已经能满足要求。
  应该可以。jquerysetoncontainer的animation是最合适的。另外就是尽量少用requestanimationframe等惰性方法,尽量用throttle,不然每一帧获取网络动画都很耗时。
  用ajax去请求图片,然后保存到一个图片,用loader渲染,
  1.加载图片2.利用js,
  看看这个,反正我是这么做的,确保它会在页面中等待解析ie==0/10ie6/9/11ie11/12(mozilla/5.0(windowsnt10.0;win64;x64)applewebkit/537.36(khtml,likegecko)chrome/73.0.3686.0safari/537.36等待等待一段时间保存图片。等待有时间了再解析返回结果。

jquery抓取网页内容(Excel教程Excel函数Excel表格制作Excel2010Excel实用技巧Excel视频教程)

网站优化优采云 发表了文章 • 0 个评论 • 53 次浏览 • 2022-03-31 12:02 • 来自相关话题

  jquery抓取网页内容(Excel教程Excel函数Excel表格制作Excel2010Excel实用技巧Excel视频教程)
  up=urllib2.urlopen(url)#打开目标页面并存入变量up
  cont=up.read()#从up读取HTML文件
  key1='key2="target"#设置关键字2
  pa=cont.find(key1)#查找关键字1的位置
  pt=cont.find(key2,pa)#查找关键字2的位置(从单词1的后面开始)
  urlx=cont[pa:pt]#获取关键字1和关键字2之间的内容(即想要的数据)
  打印网址
  但是在动态页面中,显示的内容往往不是通过HTML页面呈现,而是通过调用js等从数据库中获取数据,回显到网页中。以国家发改委网站上的“备案信息”( )为例,抓取该页面的部分备案项目。例如””。
  因此,在浏览器中打开此页面:
  相关信息显示的很全,但是如果按照前面的方法:
  复制代码代码如下:
  up=urllib2.urlopen(url)
  续=up.read()
  所谓动态页面也是通过Http请求实现的。动态页面的生成是基于不同用户输入的需求。使用python模拟用户的输入,填写相应的表单并发送请求和参数较多的一般静态请求传递
  Python爬取动态和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或IP限制。
  如果你要抓取的动态页面没有这些限制,可以使用和抓取静态页面一样的方法,比如如下:
  导入 urllib2url = "xxxxxx" 打印 urllib2.urlopen(url).read()
  如何使用Python爬取动态页面信息————Python爬取动态页面和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或ip限制。如果要捕获的动态页面没有这些限制,那么可以使用和静态页面一样的方法,比如: import urllib2 url = "xxxxxx" print urllib2.urlopen(url).read ()
  python如何抓取动态页面内容?- —— 1.了解网页抓取的逻辑流程请参考:【整理】关于抓取网页、分析网页内容、模拟登陆的逻辑/流程网站及注意事项&lt; @2.重用工具分析所需内容是如何生成的【总结】浏览器中的开发者工具(IE9的F12和Chrome的Ctrl+Shift+I)——网页分析的强大工具也可以用,不过我用过,感觉不如IE9的F12好用。3.已经分析过了,找出具体是哪个url生成了你需要的数据,然后用Python实现对应的代码。
  python3如何爬取动态加载的网页信息——方法一在页面中查找xhr请求,获取实际请求参数。直接获取相关搜索的请求返回码,然后进行数据排序。方法 2 模拟浏览器操作,例如使用 Selenium 模块。
  如何使用Python抓取动态页面信息——selenium webdriverFirefox()implicitly_wait(3)查看网页请求获取数据时一般会请求其他地址,也可以获取信息。你的问题太笼统了,所以这个是唯一的答案
  如何使用Python抓取动态页面信息—— 1、使用模拟浏览器 2、找到对应的ajax url,提交ajax请求,如果是js动态加载的,可以使用pyV8第三方包解析js
  如何使用Python捕获动态页面信息——先从本文中捕获动态页面数据的相关工具和库开始:1. python 2.7 2. pyqt 3.@ &gt; spynner(在安装过程中,其他一些依赖库也会自动下载在线安装) 4. BeautifulSoup 5. ide工具是pycharm(当然这只是个人喜好,其他ide工具也可用于)...
  如何使用Python捕获动态页面信息——1.自己分析ajax2.使用python控制webkit、无界面浏览器、或者selenuim技术直接获取解析加载的html
  如何使用Python抓取动态页面信息——这个要先研究动态页面中不变的部分,然后通过字符串处理提取出需要的信息
  如何使用Python抓取动态页面信息——很久以前,在学习Python网页编程的时候,涉及到一个Python urllib。您可以使用 urllib.urlopen("url").read() 轻松读取页面上的信息静态信息。但是随着时代的发展,越来越多的网页使用javascript、jQuery、PHP等语言来动态生成页面信息。所以...
  如何使用python爬取动态页面信息————python爬取动态页面和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或IP限制。如果你想捕获的动态页面没有这些限制,那么你可以使用和静态页面一样的方法,例如: import urllib2url = "xxxxxx" print urllib2.urlopen(url).read( ) 查看全部

  jquery抓取网页内容(Excel教程Excel函数Excel表格制作Excel2010Excel实用技巧Excel视频教程)
  up=urllib2.urlopen(url)#打开目标页面并存入变量up
  cont=up.read()#从up读取HTML文件
  key1='key2="target"#设置关键字2
  pa=cont.find(key1)#查找关键字1的位置
  pt=cont.find(key2,pa)#查找关键字2的位置(从单词1的后面开始)
  urlx=cont[pa:pt]#获取关键字1和关键字2之间的内容(即想要的数据)
  打印网址
  但是在动态页面中,显示的内容往往不是通过HTML页面呈现,而是通过调用js等从数据库中获取数据,回显到网页中。以国家发改委网站上的“备案信息”( )为例,抓取该页面的部分备案项目。例如””。
  因此,在浏览器中打开此页面:
  相关信息显示的很全,但是如果按照前面的方法:
  复制代码代码如下:
  up=urllib2.urlopen(url)
  续=up.read()
  所谓动态页面也是通过Http请求实现的。动态页面的生成是基于不同用户输入的需求。使用python模拟用户的输入,填写相应的表单并发送请求和参数较多的一般静态请求传递
  Python爬取动态和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或IP限制。
  如果你要抓取的动态页面没有这些限制,可以使用和抓取静态页面一样的方法,比如如下:
  导入 urllib2url = "xxxxxx" 打印 urllib2.urlopen(url).read()
  如何使用Python爬取动态页面信息————Python爬取动态页面和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或ip限制。如果要捕获的动态页面没有这些限制,那么可以使用和静态页面一样的方法,比如: import urllib2 url = "xxxxxx" print urllib2.urlopen(url).read ()
  python如何抓取动态页面内容?- —— 1.了解网页抓取的逻辑流程请参考:【整理】关于抓取网页、分析网页内容、模拟登陆的逻辑/流程网站及注意事项&lt; @2.重用工具分析所需内容是如何生成的【总结】浏览器中的开发者工具(IE9的F12和Chrome的Ctrl+Shift+I)——网页分析的强大工具也可以用,不过我用过,感觉不如IE9的F12好用。3.已经分析过了,找出具体是哪个url生成了你需要的数据,然后用Python实现对应的代码。
  python3如何爬取动态加载的网页信息——方法一在页面中查找xhr请求,获取实际请求参数。直接获取相关搜索的请求返回码,然后进行数据排序。方法 2 模拟浏览器操作,例如使用 Selenium 模块。
  如何使用Python抓取动态页面信息——selenium webdriverFirefox()implicitly_wait(3)查看网页请求获取数据时一般会请求其他地址,也可以获取信息。你的问题太笼统了,所以这个是唯一的答案
  如何使用Python抓取动态页面信息—— 1、使用模拟浏览器 2、找到对应的ajax url,提交ajax请求,如果是js动态加载的,可以使用pyV8第三方包解析js
  如何使用Python捕获动态页面信息——先从本文中捕获动态页面数据的相关工具和库开始:1. python 2.7 2. pyqt 3.@ &gt; spynner(在安装过程中,其他一些依赖库也会自动下载在线安装) 4. BeautifulSoup 5. ide工具是pycharm(当然这只是个人喜好,其他ide工具也可用于)...
  如何使用Python捕获动态页面信息——1.自己分析ajax2.使用python控制webkit、无界面浏览器、或者selenuim技术直接获取解析加载的html
  如何使用Python抓取动态页面信息——这个要先研究动态页面中不变的部分,然后通过字符串处理提取出需要的信息
  如何使用Python抓取动态页面信息——很久以前,在学习Python网页编程的时候,涉及到一个Python urllib。您可以使用 urllib.urlopen("url").read() 轻松读取页面上的信息静态信息。但是随着时代的发展,越来越多的网页使用javascript、jQuery、PHP等语言来动态生成页面信息。所以...
  如何使用python爬取动态页面信息————python爬取动态页面和静态页面基本相同。不同的是,一些动态页面对请求头有限制(如cookie\user agent)或IP限制。如果你想捕获的动态页面没有这些限制,那么你可以使用和静态页面一样的方法,例如: import urllib2url = "xxxxxx" print urllib2.urlopen(url).read( )

官方客服QQ群

微信人工客服

QQ人工客服


线