scrapy
[TOC]
开始
scrapy安装
-
首先手动安装windows版本的
Twisted
https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
pip install Twisted-18.4.0-cp36-cp36m-win_amd64.whl
-
安装
scrapy
pip install -i https://pypi.douban.com/simple/ scrapy
-
windows系统额外需要安装
pypiwin32
pip install -i https://pypi.douban.com/simple pypiwin32
新建项目
开始一个项目
E:svnProject> scrapy startproject TestSpider
生成一个新的爬虫(generate)
E:svnProject> cd TestSpider
E:svnProjectTestSpider> scrapy genspider dongfeng www.dongfe.com
启动一个爬虫
E:svnProjectTestSpider> scrapy crawl dongfeng
SHELL
模式
> scrapy shell http://www.dongfe.com/ # 命令行调试该网页
pycharm
调试启动文件
E:svnProjectTestSpider> vim main.py
import sys
import os
from scrapy.cmdline import execute
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(BASE_DIR)
# scrapy crawl dongfeng
execute(["scrapy", "crawl", "dongfeng"])
项目基本配置
E:svnProjectTestSpiderTestSpider> vim settings.py
ROBOTSTXT_OBEY = False # 不要遵循网站robots文件
XPATH
表达式 | 说明 |
---|---|
/body | 选出当前选择器的根元素body |
/body/div | 选取当前选择器文档的根元素body的所有div子元素 |
/body/div[1] | 选取body根元素下面第一个div子元素 |
/body/div[last()] | 选取body根元素下面最后一个div子元素 |
/body/div[last()-1] | 选取body根元素下面倒数第二个div子元素 |
//div | 选取所有div子元素(不论出现在文档任何地方) |
body//div | 选取所有属于body元素的后代的div元素(不论出现在body下的任何地方) |
/body/@id | 选取当前选择器文档的根元素body的id属性 |
//@class | 选取所有元素的class属性 |
//div[@class] | 选取所有拥有class属性的div元素 |
//div[@class='bold'] | 选取所有class属性等于bold的div元素 |
//div[contains(@class,'bold')] | 选取所有class属性包含bold的div元素 |
/div/* | 选取当前文档根元素div的所有子元素 |
//* | 选取文档所有节点 |
//div[@*] | 获取所有带属性的div元素 |
//div/a | //div/p | 选取所有div元素下面的子元素a和子元素p(并集) |
//p[@id='content']/text() | 选取id为content的p标签的内容(子元素的标签和内容都不会获取到) |
> 注意: XPATH在选择时,参考的是HTML源码,而不是JS加载后的HTML代码
操作例子
title_selector = response.xpath("//div[@class='entry-header']/h1/text()")
title_str = title_selector.extract()[0]
CSS选择器
表达式 | 说明 |
---|---|
* | 选择所有节点 |
#container | 选择Id为container的节点 |
.container | 选取所有包含container类的节点 |
li a | 选取所有li下的所有后代a元素(子和孙等所有的都会选中) |
ul + p | 选取ul后面的第一个相邻兄弟p元素 |
div#container > ul | 选取id为container的div的所有ul子元素 |
ul ~ p | 选取与ul元素后面的所有兄弟p元素 |
a[title] | 选取所有有title属性的a元素 |
a[href='http://taobao.com'] | 选取所有href属性等于http://taobao.com的a元素 |
a[href*='taobao'] | 选取所有href属性包含taobao的a元素 |
a[href^='http'] | 选取所有href属性开头为http的a元素 |
a[href$='.com'] | 选取所有href属性结尾为.com的a元素 |
input[type=radio]:checked | 选取选中的radio的input元素 |
div:not(#container) | 选取所有id非container的div元素 |
li:nth-child(3) | 选取第三个li元素 |
tr:nth-child(2n) | 选取偶数位的tr元素 |
a::attr(href) | 获取所有a元素的href属性值 |
操作例子
h1_selector = response.css(".container h1::text") # 选取h1标题的内容
h1_str = h1_selector.extract_first() # 取出数组第一个,如果没有为空
爬虫
爬取某网站文章列表例子
>>> vim ArticleSpider/spiders/jobbole.py
import scrapy
from scrapy.http import Request
from urllib import parse
import re
from ArticleSpider.items import ArticleItem
from ArticleSpider.utils.common import get_md5 # url转md5
class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['blog.jobbole.com']
start_urls = ['http://blog.jobbole.com/all-posts/']
def parse(self, response):
"""
文章列表页的文章链接解析
:param response:
:return:
"""
css = "#archive > .post > .post-thumb > a"
article_urls_selector = response.css(css) # 获取当前列表页所有文章的链接
for article_url_selector in article_urls_selector:
head_img_url = article_url_selector.css("img::attr(src)").extract_first() # 封面URL
head_img_full_url = parse.urljoin(response.url, head_img_url) # 封面图片完整URL
article_url = article_url_selector.css("a::attr(href)").extract_first("") # 文章URL
article_full_url = parse.urljoin(response.url, article_url) # 智能的拼接URL,相对地址直接对接;绝对地址只取出域名对接;完全地址不对接,直接获取。
yield Request(url=article_full_url, callback=self.article_parse, meta={"head_img_full_url": head_img_full_url}) # 请求文章详情页并设置回调函数解析内容和meta传参
next_url = response.css(".next.page-numbers::attr(href)").extract_first("")
if next_url:
yield Request(url=parse.urljoin(response.url, next_url), callback=self.parse) # 下一页文章列表使用递归
def article_parse(self, response):
"""
文章详情页的内容解析
:param response:
:return:
"""
title = response.css(".grid-8 .entry-header > h1::text").extract_first("")