一、利用Scrapy框架抓取数据

1.1 Scrapy吸引人的地方在于它是一个框架。
任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。

python爬虫-scrapy框架_xml

1.2、Scrapy主要包括了以下组件:
​​引擎(Scrapy) 用来处理整个系统的数据流处理, 触发事务(框架核心)
调度器(Scheduler)用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回。
可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列,
由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
下载器(Downloader) 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
项目管道(Pipeline) 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。
当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
下载器中间件(Downloader Middlewares) 位于Scrapy引擎和下载器之间的框架,
主要是处理Scrapy引擎与下载器之间的请求及响应。
爬虫中间件(Spider Middlewares) 介于Scrapy引擎和爬虫之间的框架,
主要工作是处理蜘蛛的响应输入和请求输出。
调度中间件(Scheduler Middewares) 介于Scrapy引擎和调度之间的中间件,
从Scrapy引擎发送到调度的请求和响应。
​​
1.3、Scrapy运行流程大概如下:
​​◆ 引擎从调度器中取出一个链接(URL)用于接下来的抓取
◆ 引擎把URL封装成一个请求(Request)传给下载器
◆ 下载器把资源下载下来,并封装成应答包(Response)
◆ 爬虫解析Response
◆ 解析出实体(Item),则交给实体管道进行进一步的处理
◆ 解析出的是链接(URL),则把URL交给调度器等待抓取
​​
1.4 安装模块(可以在Anaconda环境中执行)
依次执行下列命令安装
​​pip install lxml​​
​​lxml是个非常有用的python库,它可以灵活高效地解析xml,
与BeautifulSoup、requests结合,是编写爬虫的标准姿势。
​​
​​pip install zope.interface​​
​​Python支持多继承,但是不支持接口,zope.inteface是其三方的接口实现库,
在twisted中有大量使用
​​
​​pip install twisted​​
​​若安装出错:error: Microsoft Visual C++ 14.0 is required.
安装 vc_redist15.x86.exe
一个Twisted程序由reactor发起的主循环和一些回调函数组成。当事件发生了,
比如一个client连接到了server,这时候服务器端的事件会被触发执行。
​​
​​pip install pyOpenSSL​​
​​生成网络安全需要的CA和证书
​​
​​pip install pywin32​​
​​若安装出错
执行安装:Twisted-18.4.0-cp36-cp36m-win32.whl
pywin32是一个Python库,为python提供访问Windows API的扩展,
提供了齐全的windows常量、接口、线程以及COM机制等等
若安装出错
下载地址:https://sourceforge.net/projects/pywin32/files/pywin32/
下载后双击安装
若之后仍显示cannot import name '_win32stdio‘
则cmd中运行pip install pypiwin32
​​
​​pip install scrapy​​
​​scrapy不同于简单的单线程爬虫,采用scrapy框架写python爬虫需要生成许多个文件,
这一件类似于java里面的web框架,许多工作都可以通过一些配置文件来完成。
​​
1.5 创建项目
​​实战:Scrapy结合CSS+xpath:爬取梦幻西游音乐​​
​​scrapy 不同于简单的单线程爬虫,采用scrapy 框架写python爬虫需要生成许多个文件,
这一件类似于java里面的web框架,许多工作都可以通过一些配置文件来完成。
​​
命令:​​scrapy startproject Preject_name​​
项目创建好后目录结构如下:

python爬虫-scrapy框架_xml_02

​​scrapy.cfg:  项目的配置文件
scrapyTest1/:项目的Python模块,将会从这里引用代码
scrapyTest1 /items.py:项目的items文件
用来存放抓取内容容器的文件
scrapyTest1 /pipelines.py:负责处理爬虫从网页中抽取的实体,持久化实体、验证实体的有效性、清除不需要的信息
scrapyTest1 /settings.py: 项目的设置文件
scrapyTest1 /spiders/: 存储爬虫的目录
​​

python爬虫-scrapy框架_ide_03

​​◆ 找到douban项目文件夹下的items.py文件明确需要抓取的目标
import scrapy
from scrapy import Field,Item
class DoubanItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title=Field() # 电影名称
movieInfo=Field() # 电影介绍
star = Field() # 评分
critical = Field() # 评分人数
quote = Field() #经典的话
pass

◆ 在项目文件夹下的spiders文件夹下新建一个py文件,制作爬虫文件:doubanTest.py
from scrapy.spiders import CrawlSpider
from scrapy.http import Request
from scrapy.selector import Selector
from douban.items import DoubanItem # 导入items.py文件中的DoubanItem类
import re

class Douban(CrawlSpider): # 继承自CrawlSpider
name="doubanTest" # 爬虫文件的名称,与文件名一致,类似于Java中的类
start_urls=["http://movie.douban.com/top250"]
def parse(self, response): # 定义解析器函数,获取文件内容
item=DoubanItem() # 通过item中的类DoubanItem实例化对象
selector=Selector(response) # 处理返回结果
Movies=selector.xpath('//div[@class="info"]') # 获取所有包含电影信息的div
# 遍历每条div获取相应信息
for eachMovie in Movies:
fullTitle=eachMovie.xpath("div[@class='hd']/a/span[@class='title'][1]/text()").extract()
star=eachMovie.xpath("div[@class='bd']/div[@class='star']/span[2]/text()").extract()
movieInfo = eachMovie.xpath("div[@class='bd']/p[1]/text()").extract()
craticalStr=eachMovie.xpath("div[@class='bd']/div[@class='star']/span[4]/text()").extract()[0]
critical=re.sub("\D","",craticalStr) # 使用空字符串代替"\D"
quote=eachMovie.xpath("div[@class='bd']/p[@class='quote']/span[1]/text()").extract()
if quote: # 部分电影不存在quote
quote=quote[0]
else:
quote="无评论"
为第一步items要抓取的目标赋值
item["title"]=fullTitle
item["movieInfo"]=movieInfo[0].strip()
item["star"]=star
item["critical"]=critical
item["quote"]=quote
yield item # 提交给item pipeline

◆ 在settings.py文件中添加headers,代理,保存文件位置、类型等
BOT_NAME = 'douban'
SPIDER_MODULES = ['douban.spiders']
NEWSPIDER_MODULE = 'douban.spiders'
USER_AGENT='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) \
AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'
FEED_URI=u'file///E:/Python_WorkSpace/Scrapy/douban/doubanFilm.csv'
# 文件存放位置,绝对位置,注意使用"/"
FEED_FORMAT='CSV' #保存文件格式

◆ 在于items.py文件同级的文件夹创建主函数,运行爬虫文件,实现爬虫操作
from scrapy import cmdline
cmdline.execute("scrapy crawl doubanTest".split()) # 注意执行文件的名称​​

二、 ​​xpath​​选择器

​举例: <?xml version="1.0" encoding="UTF-8"?> <bookstore> <book> <title lang="eng">Harry Potter</title> <price>29.99</price> </book> <book> <title lang="eng">Learning XML</title> <price>39.95</price> </book> </bookstore>​

XML 节点选择

节点是通过沿着路径或者 step 来选取的。

表达式描述nodename选取此节点的所有子节点。/从根节点选取。//当前节点选择文档中的节点,而不考虑它们的位置。.选取当前节点。..选取当前节点的父节点。@选取属性。路径表达式结果bookstore选取 bookstore 元素的所有子节点。/bookstore选取根元素 bookstore。 注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!bookstore/book选取属于 bookstore 的子元素的所有 book 元素。//book选取所有 book 子元素,而不管它们在文档中的位置。bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。//@lang选取名为 lang 的所有属性。

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

路径表达式结果/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’]选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。/bookstore/book[price>35.00]选取 bookstore 元素的所有 book 元素,且 price 元素的值须大于 35.00。/bookstore/book[price>35.00]/title选取 bookstore 元素中的 book 元素的所有 title 元素,且 price 元素的值须大于 35.00。

XPath 通配符可用来选取未知的 XML 元素。

通配符描述通配符描述*匹配任何元素节点。/bookstore/*选取 bookstore 元素的所有子元素。@*匹配任何属性节点。//*选取文档中的所有元素。node()匹配任何类型的节点。//title[@*]选取所有带有属性的 title 元素。

使用​​"|"​​运算符,您可以选取若干个路径。

路径表达式结果//book/title//book/price//title//price/bookstore/book/title//price

三、 ​​CSS​​选择器

CSS选择器用于选择你想要的元素的样式的模式。

选择器示例示例说明CSS​.class​.intro选择所有class=”intro”的元素1​​#id​firstname选择所有id=”firstname”的元素1​​*​​*选择所有元素2​element​p选择所有元素1​element,element​div,p选择所有元素和元素1​element element​div p选择元素内的所有元素1​element>element​div>p选择所有父级是 元素的 元素2​element+element​div+p选择所有紧接着元素之后的元素2​​[attribute]​​[target]选择所有带有target属性元素2​​[attribute=value]​​[target=-blank]选择所有使用target=”-blank”的元素2​​[attribute~=value]​​[title~=flower]选择标题属性包含单词”flower”的所有元素2​​[attribute |=language]​​[lang|=en]选择一个lang属性的起始值=”EN”的所有元素2​​:link​​a:link选择所有未访问链接1​​:visited​​a:visited选择所有访问过的链接1​​:active​​a:active选择活动链接1​​:hover​​a:hover选择鼠标在链接上面时1​​:focus​​input:focus选择具有焦点的输入元素2​​:first-letter​​p:first-letter选择每一个元素的第一个字母1​​:first-line​​p:first-line选择每一个元素的第一行1​​:first-child​​p:first-child指定只有当元素是其父级的第一个子级的样式。2​​:before​​p:before在每个元素之前插入内容2​​:after​​p:after在每个元素之后插入内容2​​:lang(language)​​p:lang(it)选择一个lang属性的起始值=”it”的所有元素2​element1~*element2*​​p~ul选择p元素之后的每一个ul元素3​​[attribute^=value]​​a[src^=”https”]选择每一个src属性的值以”https”开头的元素3​​[attribute$=value]​​a[src$=”.pdf”]选择每一个src属性的值以”.pdf”结尾的元素3​​[attribute*=value]​​a[src*=”runoob”]选择每一个src属性的值包含子字符串”runoob”的元素3​​:first-of-type​​p:first-of-type选择每个p元素是其父级的第一个p元素3​​:last-of-type​​p:last-of-type选择每个p元素是其父级的最后一个p元素3​​:only-of-type​​p:only-of-type选择每个p元素是其父级的唯一p元素3​​:only-child​​p:only-child选择每个p元素是其父级的唯一子元素3​​:nth-child(n)​​p:nth-child(2)选择每个p元素是其父级的第二个子元素3​​:nth-last-child(n)​​p:nth-last-child(2)选择每个p元素的是其父级的第二个子元素,从最后一个子项计数3​​:nth-of-type(n)​​p:nth-of-type(2)选择每个p元素是其父级的第二个p元素3​​:nth-last-of-type(n)​​p:nth-last-of-type(2)选择每个p元素的是其父级的第二个p元素,从最后一个子项计数3​​:last-child​​p:last-child选择每个p元素是其父级的最后一个子级。3​​:root​​:root选择文档的根元素3​​:empty​​p:empty选择每个没有任何子级的p元素(包括文本节点)3​​:target​​news:target选择当前活动的#news元素(包含该锚名称的点击的URL)3​​:enabled​​input:enabled选择每一个已启用的输入元素3​​:disabled​​input:disabled选择每一个禁用的输入元素3​​:checked​​input:checked选择每个选中的输入元素3​​:not(selector)​​:not(p)选择每个并非p元素的元素3​​::selection​​::selection匹配元素中被用户选中或处于高亮状态的部分3​​:out-of-range​​:out-of-range匹配值在指定区间之外的input元素3​​:in-range​​:in-range匹配值在指定区间之内的input元素3​​:read-write​​:read-write用于匹配可读及可写的元素3​​:read-only​​:read-only用于匹配设置 “readonly”(只读) 属性的元素3​​:optional​​:optional用于匹配可选的输入元素3​​:required​​:required用于匹配设置了 “required” 属性的元素3​​:valid​​:valid用于匹配输入值为合法的元素3​​:invalid​​:invalid用于匹配输入值为非法的元素

四、PhantomJS & Selenium

PhantomJS: ​​了解详情​

官网:​​http://phantomjs.org/download.html​​ (支持Windows/Linux/Mac OS)

Selenium

官网:​​http://selenium-python.readthedocs.io/index.html​​​
官网下载安装或者:
执行命令:​​​pip install selenium​​​
前提1:安装chrome浏览器,注意更新版本
前提2:下载Chromedrive,放在chrome.exe目录下,并配置环境变量
示例1:

​from selenium import webdriver url = 'https://www.baidu.com' driver = webdriver.Chrome() driver.maximize_window() driver.get(url)​

示例2:

python爬虫-scrapy框架_xml_04

​​from selenium import webdriver
url = 'https://movie.douban.com/chart'
driver = webdriver.Chrome()
driver.get(url)

tables = driver.find_elements_by_tag_name('table')
tables.pop(0)
for i,v in enumerate(tables):
film_name = v.find_elements_by_class_name('pl2')[0].\
find_elements_by_tag_name('a')[0].text
actor = v.find_elements_by_class_name('pl')[0].text
comment = v.find_elements_by_class_name('pl2')[0]. \
find_elements_by_tag_name('div')[0].text
print(film_name)
print('-----------------1--------------------')
print(actor)
print('-----------------2-------------------')
print(comment)​​