爬虫实践-豆瓣读书Top250

爬虫学习与实践

  • 一、爬虫介绍
  • 二、爬虫原理
    • TCP3次握手,4次挥手过程
  • 三、页面解析之数据提取
  • 四、正则表达式
  • 五、实践
    • 1. 抓取百度贴吧
    • 2. 拉钩招聘网
  • 六、 进阶版

一、爬虫介绍

网络爬虫,其实叫作网络数据采集更容易理解。就是通过编程向网络服务器请求数据(HTML表单),然后解析HTML,提取出自己想要的数据

爬虫步骤:

  1. 根据url获取HTML数据
  2. 解析HTML,获取目标信息
  3. 存储数据
  4. 预处理
  5. 排名,提供检索服务

二、爬虫原理

爬虫是 模拟用户在浏览器或者某个应用上的操作,把操作的过程、实现自动化的程序
网络爬虫要做的,简单来说,就是实现浏览器的功能。通过指定url,直接返回给用户所需要的数据,而不需要一步步人工去操纵浏览器获取。
网络爬虫的基本工作流程如下:
a . 首先选取一部分精心挑选的种子URL;
b. 将这些URL放入待抓取URL队列;
c. 从待抓取URL队列中取出待抓取在URL,解析DNS,并且得到主机的ip,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。
d. 分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环。

TCP3次握手,4次挥手过程

(1)客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报(2)服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志。因此它表示对刚才客户端SYN报文的回应;同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯。
(3)客户必须再次回应服务段一个ACK报文,这是报文段3
连接终止协议(四次挥手):
(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送(报文段4)。
(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。
(3) 服务器关闭客户端的连接,发送一个FIN给客户端(报文段6)。
(4) 客户段发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。

三、页面解析之数据提取

一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值,内容一般分为两部分,非结构化的文本,或结构化的文本。

关于结构化的数据
JSON、XML

关于HTML文本(包含JavaScript代码):
HTML文本(包含JavaScript代码)是最常见的数据格式,理应属于结构化的文本组织,但因为一般我们需要的关键信息并非直接可以得到,需要进行对HTML的解析查找,甚至一些字符串操作才能得到,所以还是归类于非结构化的数据处理中。
把网页比作一个人,那么HTML便是他的骨架,JS便是他的肌肉,CSS便是它的衣服。
常见解析方式如下:XPath、CSS选择器、正则表达式
比如一段文本:
例如一篇文章,或者一句话,我们的初衷是提取有效信息,所以如果是滞后处理,可以直接存储,如果是需要实时提取有用信息,常见的处理方式如下:

分词根据抓取的网站类型,使用不同词库,进行基本的分词,然后变成词频统计,类似于向量的表示,词为方向,词频为长度。

NLP自然语言处理,进行语义分析,用结果表示,例如正负面等。

四、正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑。

常见匹配符:
^ — 与字符串开始的地方匹配,不匹配任何字符;
$ — 与字符串结束的地方匹配,不匹配任何字符;
\b — 匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符;
\B — \b取非,即匹配一个非单词边界;
爬虫实践-豆瓣读书Top250_第1张图片

五、实践

1. 抓取百度贴吧

源码

# -*- coding:utf-8 -*-
import urllib2
import urllib
from lxml import etree
import chardet
import json
import codecs
def GetTimeByArticle(url):
    request = urllib2.Request(url)
    response = urllib2.urlopen(request)
    resHtml = response.read()
    html = etree.HTML(resHtml)
    time = html.xpath('//span[@class="tail-info"]')[1].text
    print time
    return time
def main():
    output = codecs.open('tieba0812.json', 'w', encoding='utf-8')
    for pn in range(0, 250, 50):
        kw = u'网络爬虫'.encode('utf-8')
        url = 'http://tieba.baidu.com/f?kw=' + urllib.quote(kw) + '&ie=utf-8&pn=' + str(pn)
        print url
        request = urllib2.Request(url)
        response = urllib2.urlopen(request)
        resHtml = response.read()
        print resHtml
        html_dom = etree.HTML(resHtml)
        # print etree.tostring(html_dom)
        html = html_dom
        # site = html.xpath('//li[@data-field]')[0]
        for site in html.xpath('//li[@data-field]'):
            # print etree.tostring(site.xpath('.//a')[0])
            title = site.xpath('.//a')[0].text
            Article_url = site.xpath('.//a')[0].attrib['href']
            reply_date = GetTimeByArticle('http://tieba.baidu.com' + Article_url)
            jieshao = site.xpath('.//*[@class="threadlist_abs threadlist_abs_onlyline "]')[0].text.strip()
            author = site.xpath('.//*[@class="frs-author-name j_user_card "]')[0].text.strip()
            lastName = site.xpath('.//*[@class="frs-author-name j_user_card "]')[1].text.strip()
            print title, jieshao, Article_url, author, lastName
            item = {}
            item['title'] = title
            item['author'] = author
            item['lastName'] = lastName
            item['reply_date'] = reply_date
            print item
            line = json.dumps(item, ensure_ascii=False)
            print line
            print type(line)
            output.write(line + "\n")
        output.close()
    print 'end'
if __name__ == '__main__':
    main()

2. 拉钩招聘网

源码:

from lxml import etree
import requests
import re
response = requests.get('http://www.lagou.com/jobs/2101463.html')
resHtml = response.text
html = etree.HTML(resHtml)
title = html.xpath('//h1[@title]')[0].attrib['title']
#salary= html.xpath('//span[@class="red"]')[0].text
salary = html.xpath('//dd[@class="job_request"]/p/span')[0].text
worklocation = html.xpath('//dd[@class="job_request"]/p/span')[1].text
experience = html.xpath('//dd[@class="job_request"]/p/span')[2].text
education = html.xpath('//dd[@class="job_request"]/p/span')[3].text
worktype = html.xpath('//dd[@class="job_request"]/p/span')[4].text
Temptation = html.xpath('//dd[@class="job_request"]/p[2]')[0].text
print salary,worklocation,experience,education,worktype,Temptation
description_tag = html.xpath('//dd[@class="job_bt"]')[0]
description =  etree.tostring( description_tag,encoding='utf-8')
#print description
deal_descp =  re.sub('<.*?>','',description)
print deal_descp.strip()
publisher_name =  html.xpath('//*[@class="publisher_name"]//@title')[0]
pos =  html.xpath('//*[@class="pos"]')[0].text
chuli_lv =  html.xpath('//*[@class="data"]')[0].text
chuli_yongshi =  html.xpath('//*[@class="data"]')[1].text
print chuli_lv,chuli_yongshi,pos,publisher_name

六、 进阶版

爬虫框架,其中比较好用的是 Scrapy 和 PySpider
PySpider
优点:分布式框架,上手更简单,操作更加简便,因为它增加了 WEB 界面,写爬虫迅速,集成了phantomjs,可以用来抓取js渲染的页面。

缺点:自定义程度低

http://docs.pyspider.org/en/latest/Quickstart/

Scrapy

优点:自定义程度高,比 PySpider更底层一些,适合学习研究,需要学习的相关知识多,拿来研究分布式和多线程等等是最合适不过的。

缺点:非分布式框架(可以用scrapy-redis分布式框架)

爬虫技术越来越高级,需要我们不断学习、探索,今天就简单分享到这吧!

你可能感兴趣的:(爬虫,python,分布式)