python大作业爬虫_Python爬虫学习-爬取大规模数据(10w级)

编译环境:python v3.5.0, mac osx 10.11.4

python爬虫基础知识: Python爬虫学习-基础爬取

了解数据库 MongoDB

数据库是储存数据的地方,可以将如下的字典结构插入到MongoDB的存储单元中。

data = {

'name':peter

'id':123

...

} # 需存储的文件

数据库的构成:可以将其类比于excel表格进行理解

client = pymongo.MongoClient('localhost',27017) # 将python与mongodb进行连接,'localhost'表示本地环境, 207017是端口号

walden = client['walden'] # 创建一个库文件

以上代码可以类似于创建一个excel文件,文件名为walden

sheet_tab = walden['sheet_tab'] # 在库文件中建立一个页面名叫 sheet_tab

以上代码可以类似于创建excel文件中的一个表单

数据库的基本操作:

向页边中插入数据:sheet_tab.insert_one(data)

其中data为python中的字典结构,可有如下代码生成:

path = './walden.txt' # 输入数据的路径,为读取数据做准备

with open(path,'r') as f: # 打开文件,为只读模式

lines = f.readlines()

for index,line in enumerate(lines): # 逐个生成字典元素

data = {

'index':index,

'line' :line,

'words':len(line.split())

}

sheet_tab.insert_one(data) # 将字典元素插入库文件页面中

筛选数据库中的数据(基础筛选)

sheet_tab.find({'words':{'$lt':5}} # 选择字典中关键字words对应值小于5的所有字典元素

# $lt/$lte/$gt/$gte/$ne,依次等价于<=/>/>=/!=。(l表示less g表示greater e表示equal n表示not )

基础实战(筛选房源)

筛选小猪短租网站前三页信息储存到MongoDB中,筛选出价格大于等于500元房源,并打印出来。房源信息具体要求如下:

实战源码 (下载地址xiaozhu.py)

# -- coding: utf-8 --

import requests, time, pymongo

from bs4 import BeautifulSoup

def gender_info(soup): # 获取性别信息

gender = 'female' if soup.find_all('div','div.member_ico1') else 'male'

return gender

def get_info(url): # 获取所需的房源信息

wb_data = requests.get(url) # 向服务器请求页面

wb_data.encoding ='utf-8' # 标明编码为utf-8,以免出现解码错误

soup = BeautifulSoup(wb_data.text,'lxml') # 以lxml方式对页面进行解析

title = soup.select('h4 em')[0].text

address = soup.select('span.pr5')[0].text

price = int(soup.select('div.day_l span')[0].text)

img = soup.select('#curBigImage')[0].get('src')

hostPic = soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > a > img')[0].get('src')

hostName = soup.select('#floatRightBox > div.js_box.clearfix > div.w_240 > h6 > a')[0].text

hostGender = gender_info(soup)

data = {

'title' : title,

'address': address,

'price' : price,

'img' :img,

'hostPic' : hostPic,

'hostName' : hostName,

'hostGender' : hostGender

}

print('get_info Done')

return data

def get_list_url(pageURL): # 获取页面中所有详细房源的url

listUrl = []

wb_data = requests.get(pageURL)

wb_data.encoding = 'utf-8'

soup = BeautifulSoup(wb_data.text,'lxml')

pageList = soup.select('div.result_btm_con.lodgeunitname')

for i in pageList:

listUrl.append(i.get('detailurl'))

print('get_list_url Done')

return listUrl

def get_info_by_page(startPage, endPage, baseURL,database): # 获取整个页面的信息

for i in range(startPage,endPage+1):

url = baseURL.format(i)

listUrl = get_list_url(url)

for j in listUrl:

time.sleep(4)

dataInfo = get_info(j) # 获取每个页面的信息

database.insert_one(dataInfo) # 将信息插入到指定的页面中

print('input to database Done')

client = pymongo.MongoClient('localhost',27017) # 连接mongodb

xiaozhu = client['xiaozhu'] # 创建一个名叫xiaozhu的库文件

home_info = xiaozhu['home_info'] # 创建一个home_info的页面

pageBaseUrl = 'http://bj.xiaozhu.com/search-duanzufang-p{}-0/' # 构造共同url连接

get_info_by_page(1,3,pageBaseUrl,home_info) # 调用函数爬取信息并将信息储存到mongodb中

for info in home_info.find({'price':{'$gte':500}}): # 打印大于等于500的房源信息

print(info)

结果展示

mongoDB中的储存结果(部分截图)

价格大于等于500的房源信息(部分截图)

爬取工作分析流程

1. 观察页面特征,保证爬虫程序的通用性,即:发现边界条件和局限性。

例:爬取赶集网-北京二手市场的所有类目中属于个人的商品信息。

观察的到页面(url)变动的信息

发现页面变动边界条件

当把页面设定到150页时,我们发现返回的页面是任意四件商品的信息。因此,我们要据此,判断我们所爬取的页面是否已经到头。避免重复的信息加入到我们的数据库中。

并且通过观察发现网站这一返回操作,我们发现正常页面中有列表链接可以点击,而由于页面超出范围返回的随机商品信息页面没有。

因此我们可以用BeautifulSoup库中的find方法实现这个操作。

soup.find('ul', 'pageLink') #找到返回TRUE,没有返回FALSE

一般这种交易网站,当商品卖出后,商品有关信息页面将会被删除,所以我们爬取的过程中,可能将有商品被卖出,当我们向服务器进行请求该商品详情界面时会出现404 not found。我们可以通过status_code的方法对页面进行判断。

wb_data.status_code == 404 # 判断商品是否已被卖出,卖出则返回TRUE,没有则返回FALSE

2. 设计工作流程,保证输出效率和稳定性。

分步进行:先获取channel_list(所有频道分类的URL),保证爬取的稳定性。若是爬取类目信息,与爬取商品信息同步进行的话,当程序出现错误时,我们则什么信息也不能得到。所以分步进行可以降低风险。(图中分类项目下的所有商品详情链接)

多进程爬取: 可以利用multiprocess库中的pool函数,进行多进程爬取,这样可以提高爬取的效率。

关于进程与线程:

可以理解成多个人完成吃饭这个工作的效率:

单线程单进程:只有一个餐桌,一个人在一个餐桌上吃饭,每个人依次进行。

单线程多进程:有多个餐桌,每个餐座上只有一个人在吃饭。

单进程多线程: 只有一个餐桌,一个餐桌上可以坐多个人。

多进程多线程:多个餐座,一个餐桌上可以坐多个人。

对项目进行监测:

我们可以设计一个检测函数,隔一段时间汇报所抓取信息的数量,对项目进程进行掌控。

import timeframe page_parsing

import url_list

while True:

print(url_list.find().count())

time.sleep(5)

设计断点续传程序:

由于在我们抓取的过程中可能会遇到网络问题,导致程序终止,而我们不希望重新开始抓取,而是在中断后的地方继续进行抓取。

设计思路如下:

数据库中建立两个页面存放详情商品链接(从这一点也可以看出分步抓取的重要性)。一个存放需要抓取的(url_list1)一个存放已经抓取网商品信息的 (url_list2)。

当中断后继续抓取时,url_list1-url_list2就是剩下带抓取的商品信息页面。

db_urls = [item['url'] for item in url_list.find()] # 用列表解析式装入所有要爬取的链接

index_urls = [item['url'] for item in item_info.find()] # 所引出详情信息数据库中所有的现存的 url 字段

x = set(db_urls) # 转换成集合的数据结构

y = set(index_urls)rest_of_urls = x-y # 剩下的url

爬取结果以及源码(按设计步骤展示)

**All source code **: JacobKam-GitHub

你可能感兴趣的:(python大作业爬虫)