fireholder.github.io

伪文艺女青年,状高冷,话少爱热闹


Blog | Archive | About

Python爬虫笔记

03 Jul 2017 | Python

Requests库

方法 说明
requests.request() 构造一个请求,支撑以下各方法的基础方法
requests.get() 获取HTML网页的主要方法,对应于HTTP的GET
requests.head() 获取HTML网页头信息的方法,对应于HTTP的HEAD
requests.post() 向HTML网页提交POST请求的方法,对应于HTTP的POST
requests.put() 向HTML网页提交PUT请求的方法,对应于HTTP的PUT
requests.patch() 向HTML网页提交局部修改请求,对应于HTTP的PATCH
requests.delete() 向HTML页面提交删除请求,对应于HTTP的DELETE

get() 方法

r=requests.get(url)

Response

其中,r 为一个包含服务器资源的 Response 对象。

Response 对象属性

属性 说明
r.status_code HTTP请求的返回状态,200表示连接成功,404表示失败
r.text HTTP 响应内容的字符串形式,即,url对应的页面内容
r.encoding 从HTTP header中猜测的响应内容编码方式
r.apparent_encoding 从内容中分析出的响应内容编码方式(备选编码方式)
r.content HTTP 响应内容的二进制形式

Resquest

requests.get() 构造一个向服务器请求资源的Request对象。

requests 的方法实际上都是用request来实现的。

爬取网页的通用代码框架

def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "Exception!"

Beautiful Soup 库

Beautiful Soup库是解析、遍历、维护“标签树”的功能库。

基本元素 说明
Tag 标签,最基本的信息组织单元,分别用<>和</>标明开头和结尾
Name 标签的名字,< p>…</ p>的名字是’p’,格式:.name
Attributes 标签的属性,字典形式组织,格式:.attrs
NavigableString 标签内非属性字符串,<>…</>中字符串,格式:.string
Comment 标签内字符串的注释部分,一种特殊的Comment类型

标签树的下行遍历

属性 说明
.contents 子节点的列表,将所有儿子节点存入列表
.children 子节点的迭代类型,与.contents类似,用于循环遍历儿子节点
.descendants 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

标签树的上行遍历

属性 说明
.parent 节点的父亲标签
.parents 节点先辈标签的迭代类型,用于循环遍历先辈节点

标签树的平行遍历

平行遍历发生在同一个父节点下的各节点间。

属性 说明
.next_sibling 返回按照HTML文本顺序的下一个平行节点标签
.previous_sibling 返回按照HTML文本顺序的上一个平行节点标签
.next_siblings 迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
.previous_siblings 迭代类型,返回按照HTML文本顺序的前续所有平行节点标签

prettify() 方法

.prettify()为HTML文本<>及其内容增加更加’\n’。

使用

from bs4 import BeautifulSoup
soup = BeautifulSoup('<p>data</p>', 'html.parser')

Scrapy 爬虫框架

Scrapy不是一个函数功能库,而是一个爬虫框架。爬虫框架是实现爬虫功能的一个软件结构和功能组件集合。 爬虫框架是一个半成品,能够帮助用户实现专业网络爬虫。

Engine控制各模块数据流,不间断从Scheduler处 获得爬取请求,直至请求为空.

结构

Engine

  1. 控制所有模块之间的数据流
  2. 根据条件触发事件

Downloader

根据请求下载网页

Scheduler

对所有爬取请求进行调度管理

Downloader Middleware

Spider

  1. 解析Downloader返回的响应(Response)
  2. 产生爬取项(scraped item)
  3. 产生额外的爬取请求(Request)

Item Pipelines

  1. 以流水线方式处理Spider产生的爬取项
  2. 由一组操作顺序组成,类似流水线,每个操 作是一个Item Pipeline类型 “5+2”结构 Item Pipelines
  3. 可能操作包括:清理、检验和查重爬取项中 的HTML数据、将数据存储到数据库

Spider Middleware

流程

  1. Engine从Spider处获得爬取请求(Request)
  2. Engine将爬取请求转发给Scheduler,用于调度
  3. Engine从Scheduler处获得下一个要爬取的请求
  4. Engine将爬取请求通过中间件发送给Downloader
  5. 爬取网页后,Downloader形成响应(Response) 通过中间件发给Engine
  6. Engine将收到的响应通过中间件发送给Spider处理
  7. Spider处理响应后产生爬取项(scraped Item) 和新的爬取请求(Requests)给Engine
  8. Engine将爬取项发送给Item Pipeline(框架出口)
  9. Engine将爬取请求发送给Scheduler

Scrapy 常用命令

命令 说明 格式
startproject 创建一个新工程 scrapy startproject [dir]
genspider 创建一个爬虫 scrapy genspider [options]
settings 获得爬虫配置信息 scrapy settings [options]
crawl 运行一个爬虫 scrapy crawl
list 列出工程中所有爬虫 scrapy list
shell 启动URL调试命令行 scrapy shell [url]

爬取股票实例

stock.py

# -*- coding: utf-8 -*-
import scrapy
import re

class StockSpider(scrapy.Spider):
    name = 'stocks'
    #allowed_domains = ['stockSpider']
    start_urls = ['http://quote.eastmoney.com/stocklist.html']

    def parse(self, response):
        for href in response.css('a::attr(href)').extract():
            try:
                stock = re.findall(r"[s][hz]\d{6}", href)[0]
                url = 'https://gupiao.baidu.com/stock/' + stock + '.html'
                yield scrapy.Request(url, callback=self.parse_stock)
            except:
                continue

    def parse_stock(self, response):
        infoDict = {}
        stockInfo = response.css('.stock-bets')
        name = stockInfo.css('.bets-name').extract()[0]
        keyList = stockInfo.css('dt').extract()
        valueList = stockInfo.css('dd').extract()
        for i in range(len(keyList)):
            key = re.findall(r'>.*</dt>', keyList[i])[0][1:-5]
            try:
                val = re.findall(r'\d+\.?.*</dd>', valueList[i])[0][0:-5]
            except:
                val = '--'
            infoDict[key]=val

        infoDict.update(
            {'股票名称': re.findall('\s.*\(',name)[0].split()[0] + \
             re.findall('\>.*\<', name)[0][1:-1]})
        yield infoDict

Pipelines.py

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html


class StockspiderPipeline(object):
    def process_item(self, item, spider):
        return item

class BaidustocksInfoPipeline(object):
    def open_spider(self, spider):
        self.f = open('BaiduStockInfo.txt', 'w')

    def close_spider(self, spider):
        self.f.close()

    def process_item(self, item, spider):
        try:
            line = str(dict(item)) + '\n'
            self.f.write(line)
        except:
            pass
        return item

参考资料:中国大学mooc

comments powered by Disqus

Older · View Archive (56)

Python 机器学习 Note 1

Newer

Python 机器学习 Note 2

无监督学习之降维