本文分享的大体框架包含以下三部分

(1)首先介绍html网页,用来解析html网页的工具xpath

(2)介绍python中能够进行网络爬虫的库(requests,lxml,scrapy等)

(3)从四个案例出发有易到难依次介绍scrapy集成爬虫框架

下面开始对三部分内容逐一开始介绍。

一、html和xpath说明

1. html

超文本标记语言,是用来描述网页的一种语言。主要用于控制数据的显示和外观。HTML文档一定意义上可以被称为网页。但反过来说网页不仅仅是HTML,网页本质有三部分构成:负责内容结构的HTML,负责表现的CSS,以及负责行为的javascript。本文主要分享的是最核心的内容结构部分。

(1)html结构

完整的HTML文件至少包括标签、

标签、标签和标签,并且这些标签都是成对出现的,开头标签为<>,结束标签为>,在这两个标签之间添加内容。通过这些标签中的相关属性可以设置页面的背景色、背景图像等。

例如,我们打开豆瓣首页,摁下键盘上的F12键,打开浏览器自带“开发者工具”,可以看到一个完整的html文档结构,如下图

HTML文档结构.jpg

从上图可以看出,一个完整的html文档主要包含三部分:DTD文档头,head头部信息和body正文信息。其中DTD文档头用来告诉浏览器执行标准是什么(比如html4或是html5),head头部信息用来说明浏览器的编码方式和文档头名称,body顾名思义就是浏览器的正文部分。

(2)html标签

作为开始和结束的标记,由尖括号包围的关键词,比如 ,标签对中的第一个标签是开始标签,第二个标签是结束标签。html中常见标签如下:

html常用标签.png

html常用标签2.png

其中, “< ul >< li >”是一种嵌套顺序,无序列表,成对出现;li的父元素必须是ul或者ol,不同之处在于ol是一种有序列列表,而ul是无序列表;

(3)html属性

属性是用来修饰标签的,放在开始标签里里面,html中常见四大属性:

属性

说明

class

规定元素的类名,大多数时候用于指定样式表中的类

id

唯一标识一个元素的属性,在html里面必须是唯一的

href

指定超链接目标的url

src

指定图像的url

2. xpath

(1)xpath定义

是一种路径查询语言,简单的说就是利用一个路径表达式从html文档中找到我们需要的数据位置,进而将其写入到本地或者数据库中。(可以将xpath类比为sql结构化查询语言)

(2)xpath常见使用方法

符号

功能

//

表示在整个文本中查找,是一种相对路径

/

表示则表示从根节点开始查找,是一种绝对路径

text()

找出文本值

@

找出标签对应的属性值,比如@href就是找出对应的href链接

.

表示当前节点

..

表示当前节点的父节点

当然xpath除了上述常见用法外,还存两种比较特殊的用法:以相同的字符开头;标签套标签。

用法1:以相同的字符开头:starts-with(@属性部分,属性字符相同部分

用法2:标签套标签:string(.)

#以相同的字符开头

#比如我们想同时提取到下列html中三条文本内容的话,就需要使用starts-with方法

html1 = """

需要的内容1
需要的内容2
需要的内容3

#爬取代码

from lxml import etree

selector = etree.HTML(html1)

content = selector.xpath('//div[starts-with(@id,"test")]/text()')

for each in content:

print each

还有一种是标签套标签形式,参考如下例子

html2 = """

我左青龙,

右白虎

  • 上朱雀,
  • 下玄武,

龙头在胸口

"""

#如果我们想爬取的内容是html文档中的所有文本的话,需要使用string方法进行提取

selector2 = etree.HTML(html2)

content2 = selector2.xpath('//div[@id="test3"]')[0] #列表,只有一个元素

info = content2.xpath('string(.)')

content3 = info.replace('\n','').replace(' ','')

print content3

(3)xpath的谓语结构

该小节参考资料:阮一峰的网络日志

所谓"谓语条件",就是对路径表达式的附加条件。所有的条件,都写在方括号"[]"中,表示对节点进行进一步的筛选。例如:

Harry Potter

29.99

Learning XML

39.95

下面从几个简单的例子让大家体会一下

/bookstore/book[1] :表示选择bookstore的第一个book子元素。

/bookstore/book[last()] :表示选择bookstore的最后一个book子元素。

/bookstore/book[last()-1] :表示选择bookstore的倒数第二个book子元素。

/bookstore/book[position()<3] :表示选择bookstore的前两个book子元素。

//title[@lang] :表示选择所有具有lang属性的title节点。

//title[@lang='eng'] :表示选择所有lang属性的值等于"eng"的title节点。

二、python中能够进行网络爬虫的库

1. 安装方式

python中安装包或者模块的方式一般有以下两种:

(1)pip install xxx(xxx表示模块名字)

pip install lxml/numpy/pandas/scrapy/requests

(2)进入到python库网站下载所需模块,然后使用pip install xxx.whl安装即可

pip install lxml‑3.7.3‑cp27‑cp27m‑win_amd64.whl

2. requests

import requests

#我的简书主页

r = requests.get('http://www.jianshu.com/u/95f3a80fac3e')

# r本身是一个reponse对象,需要通过content来返回其内容

print r.content

#其实上面通过content之后得到就是一个完整的html文档,之后可以直接使用lxml等工具直接对其进行解析,下一小节会讲到lxml

print r.status_code

print r.encoding #html的编码方式,一般是UTF-8

print r.cookies

3. lxml

lxml中集成了刚才讲述的xpath这种路径查询语言;例如我们首先创建一个html文档如下

html= """

需要的内容1
需要的内容2
需要的内容3

"""

然后使用lxml对我们想要的内容进行爬取

from lxml import etree

selector = etree.HTML(html)

content = selector.xptah('path') #此处的path指的就是需要爬虫的文件路径

for item in content:

print item

前面讲到的requests通常也是配合lxml使用,首先使用requests获取到网页内容,即html文档,然后使用lxml中的xpath爬取我们所需要的内容。例子如下:

#爬取豆瓣电影top250,并将电影名称和评分打印出来

import requests

from lxml import etree

s = requests.Session() #开启一个requests会话

for id in range(0, 251, 25):

url = 'https://movie.douban.com/top250/?start-' + str(id)

r = s.get(url) #返回是一个reponse对象

r.encoding = 'utf-8'

root = etree.HTML(r.content)

items = root.xpath('//ol/li/div[@class="item"]')

# print(len(items))

for item in items:

title = item.xpath('./div[@class="info"]//a/span[@class="title"]/text()')

name = title[0].encode('gb2312', 'ignore').decode('gb2312')

# rank = item.xpath('./div[@class="pic"]/em/text()')[0]

rating = item.xpath('.//div[@class="bd"]//span[@class="rating_num"]/text()')[0]

print(name, rating)

4. 大杀器scrapy

scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。我们需要知道的是,scrapy是一种集成框架,类似于request和xpath这些方法在scrapy都有集成。

(1)scrapy安装

安装scrapy前,需要先安装lxml模块,然后按照之前说的方法进行安装就可以(我的电脑安装的是anaconda集成环境)

(2)scrapy的结构

Paste_Image.png

其中,不同模块负责不同的任务分工。首先Scheduler发出请求(Requests),Downloader负责从互联网上下载内容,将下载好的内容(Responses)交给Spiders进行解析,解析完成后将内容Item返回,当然其中可能会涉及到对于解析后数据的进一步处理,这个任务是在Pipeline中完成的。

(3)scrapy通常有两种使用方式:

直接在python脚本里定义一个爬取数据的类(参见爬虫案例1,2,3)

创建完整的scrapy项目(参见爬虫案例4);创建命令为

scrapy startproject xxx

创建完scrapy项目后,会在对应的文件下生成如下结构:

YLA943`5WMORH9SNVD~D}EA.png

其中,

spiders文件夹下面是真正爬虫的代码;

items之前提到过,是定义需要爬取的内容;

pipelines是对爬取到的数据进行的进一步处理;

settings中主要是一些环境变量和配置。

另外,scrapy有提供两个xpath选择器,HtmlXPathSelector和XmlXPathSelector,一个用于html,一个用于xml,xpath选择器有三个方法:

select(xpath): 返回一个相对于当前选中节点的选择器列表(一个xpath可能选到多个节点)

extract(): 返回选择器(列表)对应的节点的字符串(列表,类型就是python中的list)

-_ re(regex)_: 返回正则表达式匹配的字符串(分组匹配)列表

需要注意的是,如果爬取的页面相对简单,爬取内容较少,且不用对爬取到的数据做过多的后期处理,使用第一种,反之,使用第二种,当然建立完整的scrapy项目肯定可以处理简单任务。

三、爬虫案例

1. 想要爬取得内容都在同一页面

本实例中,我们通过scrapy爬取七月在线课程信息。

#scrapy runspider spider.py –o xxx.json(运行时可以在命令窗口进行)

import scrapy

class JulyeduSpider(scrapy.Spider):

name = "julyedu"

start_urls = ['https://www.julyedu.com/category/index'] #开始爬取网址,是一个list列表

# 定义解析页面函数

def parse(self, response):

for julyedu_class in response.xpath('//div[@class="course_info_box"]'):

print julyedu_class.xpath('a/h4/text()').extract_first()

print julyedu_class.xpath('a/p[@class="course-info-tip"][1]/text()').extract_first()

print julyedu_class.xpath('a/p[@class="course-info-tip"][2]/text()').extract_first()

print response.urljoin(julyedu_class.xpath('a/img[1]/@src').extract_first())

print "\n"

# 返回函数值

yield {

'title':julyedu_class.xpath('a/h4/text()').extract_first(),

'desc': julyedu_class.xpath('a/p[@class="course-info-tip"][1]/text()').extract_first(),

'time': julyedu_class.xpath('a/p[@class="course-info-tip"][2]/text()').extract_first(),

'img_url': response.urljoin(julyedu_class.xpath('a/img[1]/@src').extract_first())

}

2. 想要爬去的内容在多页,不同页之间可以进行人为拼接构成(例如博客园 )

本实例中,我们利用scrapy爬取博客园中的信息,爬取内容包括每条博文的标题、链接、作者、评论等信息

class CnBlogSpider(scrapy.Spider):

name = "cnblogs"

allowed_domains = ["cnblogs.com"]

start_urls = [ 'http://www.cnblogs.com/pick/#p%s' % p for p in xrange(1, 11) ]

#定义解析函数

def parse(self, response):

for article in response.xpath('//div[@class="post_item"]'):

print article.xpath('div[@class="post_item_body"]/h3/a/text()').extract_first().strip()

print response.urljoin(article.xpath('div[@class="post_item_body"]/h3/a/@href').extract_first()).strip()

print article.xpath('div[@class="post_item_body"]/p/text()').extract_first().strip()

print article.xpath('div[@class="post_item_body"]/div[@class="post_item_foot"]/a/text()').extract_first().strip()

print response.urljoin(article.xpath('div[@class="post_item_body"]/div/a/@href').extract_first()).strip()

print article.xpath('div[@class="post_item_body"]/div[@class="post_item_foot"]/span[@class="article_comment"]/a/text()').extract_first().strip()

print article.xpath('div[@class="post_item_body"]/div[@class="post_item_foot"]/span[@class="article_view"]/a/text()').extract_first().strip()

print ""

yield {

'title': article.xpath('div[@class="post_item_body"]/h3/a/text()').extract_first().strip(),

'link': response.urljoin(article.xpath('div[@class="post_item_body"]/h3/a/@href').extract_first()).strip(),

'summary': article.xpath('div[@class="post_item_body"]/p/text()').extract_first().strip(),

'author': article.xpath('div[@class="post_item_body"]/div[@class="post_item_foot"]/a/text()').extract_first().strip(),

'author_link': response.urljoin(article.xpath('div[@class="post_item_body"]/div/a/@href').extract_first()).strip(),

'comment': article.xpath('div[@class="post_item_body"]/div[@class="post_item_foot"]/span[@class="article_comment"]/a/text()').extract_first().strip(),

'view': article.xpath('div[@class="post_item_body"]/div[@class="post_item_foot"]/span[@class="article_view"]/a/text()').extract_first().strip(),

}

3. 想要爬取的内容存在页面跳转(例如腾讯社会新闻)

class QQNewsSpider(scrapy.Spider):

name = 'qqnews'

start_urls = ['http://news.qq.com/society_index.shtml']

def parse(self, response):

for href in response.xpath('//*[@id="news"]/div/div/div/div/em/a/@href'):

full_url = response.urljoin(href.extract())

yield scrapy.Request(full_url, callback=self.parse_question) #调用scrapy中Request方法,对合并后的网址进行分析,调用函数是parse_question

#真正意义上解析页面的函数

def parse_question(self, response):

print response.xpath('//div[@class="qq_article"]/div/h1/text()').extract_first()

print response.xpath('//span[@class="a_time"]/text()').extract_first()

print response.xpath('//span[@class="a_catalog"]/a/text()').extract_first()

print "\n".join(response.xpath('//div[@id="Cnt-Main-Article-QQ"]/p[@class="text"]/text()').extract())

print ""

yield {

'title': response.xpath('//div[@class="qq_article"]/div/h1/text()').extract_first(),

'content': "\n".join(response.xpath('//div[@id="Cnt-Main-Article-QQ"]/p[@class="text"]/text()').extract()),

'time': response.xpath('//span[@class="a_time"]/text()').extract_first(),

'cate': response.xpath('//span[@class="a_catalog"]/a/text()').extract_first(),

}

4. 通过创建scrapy工程的方式爬取全国34个省、市所属的2290个地区的历史天气预报数据,网址请戳这里,并将其保存为json格式

之前跟大家分享的案例大多是参照网络视频资源和相关博客资料,这两天由于项目需要,爬取全国34个省、市所属的2290个地区的历史天气预报数据,真正动手才发现“纸上得来终觉浅,绝知此事要躬行”的道理所在,整个过程碰到很多坑,也请教了一些牛人,终于将数据成功爬取到本地,在此记录下整个爬取过程。

1. 多级页面跳转问题

涉及到多级页面跳转才能爬取到数据的场景,有两个方面是需要特别注意的,第一是确保整个页面跳转过程的逻辑正确,第二是跳转到某个具体页面使用xpath进行路经查询时,要保证xpath的写的没有问题。

2. Scrapy终端(Scrapy shell)

Scrapy终端是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 其本意是用来测试提取数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码。

对于检查xpath路径查询语言是否正确非常,举个例子,我想要爬取某个城市2017年一月的天气中的日期数据,

Paste_Image.png

根据html中提供的路径,我写了如下的xpath表达式

day = sel.xpath('//div[@class="tqtongji2"]/ul[position()>1]/li[1]/a/text()').extract()

具体对不对,能不能爬取到相对应的日期数据,我们就可以利用scrapy shell进行检查。

(1)首先在命令窗口启动scrapy shell,启动语句也很简单,如下

scrapy shell url

其中url表示想测试的网页链接。

Paste_Image.png

(2)输入需要检查的xpath语句

Paste_Image.png

可以看到输出结果中已经正确提取出我们需要的日期数据,从而也说明我们写的xpath路径没有问题。

3. 爬虫正式开始

(1)建立scrapy工程

利用前面讲到的方法创建相应的scrapy工程,在item.py中创建需要爬去的数据如下:

Paste_Image.png

(2)爬虫spider脚本

Paste_Image.png

从页面中我们可以看到,全国各县区的城市按照A,B,C...Z顺序排列,每个字母下面包含很多城市,比如字母A下面包含阿城等地方。且每一类下面的第一个li标签是不需要的,因为第一个li标签表示的是字母A,B,C...Z等,如下图

Paste_Image.png

分析到这一步,我们可以写出一级解析函数parse来获取所有城市—链接和城市名的xpath路径查询语言,

链接如下:

sel = Selector(response)

country_urls = sel.xpath('//ul[@class="bcity"]/li[position()>1]/a/@href').extract()

城市名如下:

sel = Selector(response)

country_urls = sel.xpath('//ul[@class="bcity"]/li[position()>1]/a/text()').extract()

接下来就是每个城市(链接)进行for循环遍历,将每个城市的链接url和城市名城保存到item中,保存file_name目的在于为了待会儿写入数据时方便。将所有获取到的城市链接和城市名保存到items列表中,然后使用for循环对每个城市的进行二级页面解析,调用的是scrapy的Request方法,Request中的回调函数callback就是二级页面解析函数second_parse。一级解析函数parse的完整代码如下:

Paste_Image.png

既然说到二级页面,我们还是首先观察下二级页面的特点,以澳门历史天气详情为例

Paste_Image.png

可以看到,澳门所有历史数据(按月)都在div class = "tqtongji" 标签下面,每年的数据又被一个ul标签包围,每个ul标签下面拥有很多个li标签,分别表示一年的各个月份数据,分析到此,我们同样可以在二级解析页面函数中写出获取每个城市每个月链接和月份名称的xpath路径

链接如下:

sel = Selector(response)

month_urls = sel.xpath('//div[@class="tqtongji1"]/ul/li/a/@href').extract()

城市名如下:

sel = Selector(response)

month_titles = sel.xpath('//div[@class="tqtongji1"]/ul/li/a/text()').extract()

同样,获取到每个城市每个月份的链接后,在二级解析函数里面对每个月份进行遍历,最后仍然使用scrapy.Request对每个获取的月份链接进行解析,回调函数是三级页面解析函数detail_parse。

以下是二级页面解析函数的脚本

Paste_Image.png

最后跳转到我们最终要爬取数据的页面了,到了这一页面之后(如下图),便能够很方便的爬取到我们需要的数据。

Paste_Image.png

直接贴上最终三级页面解析函数

Paste_Image.png

到此,爬取数据的spider脚本已经全部开发完成,不过为了将数据按照城市分别保存到本地,还需要在pipeline中进行相应设置如下:

Paste_Image.png

最终爬取的效果图如下图:

Paste_Image.png

Paste_Image.png

喜欢的朋友请小小的点个赞,你的肯定会让我更有动力!!!

python 爬取数据还要下载scrapy吗_python网络爬虫之Scrapy相关推荐

  1. 爬取数据是违法的吗_网络爬虫违法吗?

    Web爬取,也称为Web抓取,数据抓取或爬虫,是一种计算机程序技术,用于从网站上抓取大量数据,并将其处理为结构化数据. Web抓取是常用的: 基本上,网页抓取是互联网的功能.例如,SEO需要创建站点地 ...

  2. python爬取淘宝商品做数据挖掘_Python 3爬虫 数据清洗与可视化实战 Python数据抓取技术 python3网络爬虫教程书籍 运用Python工具获取电商平台页面数据挖掘书籍...

    A8 书    名:Python 3爬虫 数据清洗与可视化实战 作 译 者:零一,韩要宾,黄园园 出版时间:2018-03 千 字 数:200 版    次:01-01 页    数:212 开   ...

  3. python爬取页面内容由京东提_python制作爬虫爬取京东商品评论教程

    本篇文章是python爬虫系列的第三篇,介绍如何抓取京东商城商品评论信息,并对这些评论信息进行分析和可视化.下面是要抓取的商品信息,一款女士文胸.这个商品共有红色,黑色和肤色三种颜色, 70B到90D ...

  4. 我用Python爬取了难下载的电子教材(内附代码)

    我用Python爬取了难下载的电子教材(内附代码) 第一次在CSDN上面分享经历,有点激动.本大二狗最近这段时间去不了学校又想看教材,不巧学习通上面的部分内容老师设置了不可下载啊.好在最近学习了一点P ...

  5. python爬取数据时报错:`aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host sea

    python爬取数据时报错:aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host sear ...

  6. Python:爬取数据出现response.status_code为403解决方法

    目录 前言 1. 原理 2. 代码 前言 出现403的返回结果 主要是有些服务器为了防止访问量过大,承受服务器的压力,或者是拒绝你的访问.服务器接收到这个信息,理应返回了这个403的信息 在前一块的代 ...

  7. python爬虫爬取数据如何将br去掉_Python怎么去除爬取下来的网站中的一些转义字符串 - 收获啦...

    基本方法 其实用python爬取网页很简单,只有简单的几句话 这样就可以获得到页面的内容.接下来再用正则匹配去匹配所需要的内容就行了.但是,真正要做起来,就会有各种各样的细节问题. 2.登录 这是一个 ...

  8. Python爬取小说网站下载小说

    1前言 这个小程序是用来爬取小说网站的小说的,一般的盗版小说网站都是很好爬取的 因为这种网站基本没有反爬虫机制的,所以可以直接爬取 该小程序以该网站http://www.126shu.com/15/下 ...

  9. 如何用python爬取数据_如何使用python爬取知乎数据并做简单分析

    原标题:如何使用python爬取知乎数据并做简单分析 一.使用的技术栈: 爬虫:python27 +requests+json+bs4+time 分析工具: ELK套件 开发工具:pycharm 数据 ...

最新文章

  1. 「AI初识境」被Hinton,DeepMind和斯坦福嫌弃的池化到底是什么?
  2. setting.xml的mirror、mirrorOf和pom.xml的repositories、repository的关系关联*
  3. FPGA之道(79)静态时序分析(五)外部接口的相关时序分析
  4. Windows下编译 Hadoop
  5. redis 集合操作
  6. EBS DBA指南笔记(一)
  7. 计算机在生活中应用视频,计算机在腐蚀防护中的应用教学视频
  8. android av和hdmi输出切换代码,AV转HDMI转换器有用吗?
  9. 【FFmpeg4.1.4】音视频分离器
  10. mysql sql练习题_Mysql----sql语句练习题(一)
  11. java实现咖啡店模拟_装饰者模式学习:模拟咖啡馆的点单系统来剖析装饰者模式的使用 + 装饰者模式在java I/O 中的应用...
  12. unity检测范围内敌人_怎样获取离自己距离最近的敌人
  13. FLY Windows XP Pro SP3 v3264 集成优化版 2.0
  14. jQuery常用插件库
  15. B/S结构和C/S结构详细介绍
  16. Elasticsearch:理解 Elasticsearch 中的 Percolator 数据类型及 Percolate 查询
  17. mysql主从配置duxi_Mysql主从同步配置
  18. Linux中正则表达式与文件格式化处理命令(awk/grep/sed)
  19. Navicat for MySQL 12破解
  20. 国外免费网管软件推荐

热门文章

  1. 如何使用强化学习进行量化投资?
  2. docker 命令 相关
  3. 学习 ET(1)- 开源的游戏客户端(基于 unity3d)服务端双端框架
  4. SCSI子系统基础学习笔记 (之UFS子系统) - 2.2 UFS子系统初始化之ufshcd_async_scan
  5. 周鸿祎:要替自己正名先要颠覆曾经的商业思维
  6. 在3dmax里仿unity的Unlit/Texture shader并渲染
  7. PCB 模拟Windows管理员域帐号安装软件
  8. 双喜临门|炼石荣获2023年中国网络和数据安全高峰论坛双奖项
  9. grub2磁盘安装windows
  10. 2023年TF活动正式启动