基于BeautifulSoup的Python3实战:四周实现爬虫系统笔记

章节1 第零周:开始之前

勤快写,多动手,不浮躁,坚持坚持坚持。-----慢慢来,做完美
科学上网 好的IDE 工具  理解 模仿 实战

画流程图,添加异常处理

几种爬虫比较

  1. urllib+正则:无第三方依赖
  2. requests+BeautifulSoup:library
  3. scrapy:框架

从上往下抽象程度增加,方便程度增加。“路怎么走,自己选。”

bs4官网基础知识

tag中包含多个字符串 ,可以使用 .strings 来循环获取

.stripped_strings 可以去除多余空白内容

1、prettify() 方法将Beautiful Soup的文档树格式化后以Unicode编码输出,每个XML/HTML标签都独占一行

2、想得到tag中包含的文本内容,那么可以用 get_text() 方法,这个方法获取到tag中包含的所有文版内容包括子孙tag中的内容,并将结果作为Unicode字符串返回

3、使用Beautiful Soup解析后,文档都被转换成了Unicode

4、通过Beautiful Soup输出文档时,不管输入文档是什么编码方式,输出编码均为UTF-8编码

计算时间要求很高或者计算机的时间比程序员的时间更值钱,那么就应该直接使用 lxml .

章节2 第一周:学会爬取网页信息

网页的构成   结构,样式,文档树,各种层级标签(唯一定位即可)

本地网页:

1、BeautifulSoup解析网页,类似css选择器,能在文档树里标识唯一位置即可    获取

2、找到正确元素,审查元素                                                                                   定位

3、处理标签文本,释放元素                                                                                   筛选

from bs4 import BeautifulSoup
path = './1_2_homework_required/index.html'  #这里使用了相对路径,只要你本地有这个文件就能打开
with open(path, 'r') as wb_data: # 使用with open打开本地文件,自带检测,不需要关闭
    Soup = BeautifulSoup(wb_data, 'lxml') # 解析网页内容,lxmlb比较快
    titles = Soup.select('div.caption > h4 > a') # 复制每个元素的css selector 路径即可
    stars = Soup.select('div.col-md-9 > div > div > div > div.ratings > p:nth-of-type(2)') 
  # 为了从父节点开始取,此处保留:nth-of-type(2),观察网页,多取几个星星的selector,就发现规律了

 

for title, image, star in zip(titles, images, stars):  # 使用for循环,把每个元素装到字典中,方便查询
    data = {
        'title': title.get_text(), # 使用get_text()方法取出文本
        'image': image.get('src'), # 使用get方法取出带有src的图片链接
        'star': len(star.find_all("span", class_='glyphicon glyphicon-star'))
        # 观察发现,每一个星星会有一次<span class="glyphicon glyphicon-star"></span>,所以我们统计有多少次
        # 使用find_all 统计有几处是★的样式,第一个参数定位标签名,第二个参数定位css 样式,具体可以参考BeautifulSoup 
        # 由于find_all()返回的结果是列表,我们再使用len()方法去计算列表中的元素个数,也就是星星的数量
    }
    print(data)
----------------------------
print(1,2,3,sep='\n--------\n')
'''
1
--------
2
--------
3
'''

title可以去头部标签里面取,更快

address = soup.select('div.pho_info > p')[0].get('title') # 和 get('href')通过属性取值 
cates = Soup.select('div.article-info > p.meta-info') #解析多子标签,返回列表
'cate': list(cates.stripped_strings)   
#Object.stripped_strings【父集下面所有子标签的文本信息(聚合信息)】  高级版本get_text()

外网解:requests+Beautifulsoup

1、服务器与本地交换机制  http协议,Request请求八种get,post  。Response回应,返回状态码

2、选择,大范围,利用属性缩小范围。# a[target='_blank']'  属性选择缩小范围

3、cookies伪造登录信息,headers

4、获取多页,定义函数,找每一页链接规律,列表解析式,反扒加入时间延时模块,大型网站换IP,模拟难搞的用手机页面伪造,简单。

#str(i)表示变量
urls = ['http://www.mm131.com/xinggan/3520_{}.html'.format(str(i)) for i in range(1,23,1)]
for single_url in urls:
    get_attractions(single_url)  #遍历列表并执行,保护反扒增加延时
-------------------------------------------
#另外一种,传递参数
def get_page_link(page_number):
    for each_number in range(1,page_number): # 每页24个链接,这里输入的是页码
        full_url = 'http://bj.xiaozhu.com/search-duanzufang-p{}-0/'.format(each_number)
        wb_data = requests.get(full_url)

5、登录爬取,使用cookies。扒手机页面

6、动态(异步)加载,去network找链接规律,xhr下滑几页。

字典和列表,都是可变,一般用data=None保证数据安全。

from bs4 import BeautifulSoup
import requests
import time
url = 'https://knewone.com/discover?page='
def get_page(url,data=None):
    wb_data = requests.get(url)
    soup = BeautifulSoup(wb_data.text,'lxml')
    imgs = soup.select('a.cover-inner > img')
    links = soup.select('section.content > h4 > a')
    if data==None:
        for img,title,link in zip(imgs,titles,links):
            data = {
                'img':img.get('src'),
                'link':link.get('href')
            }
            print(data) #数据被污染,从新使用置为None
def get_more_pages(start,end):
    for one in range(start,end):
        get_page(url+str(one))
        time.sleep(2) #暂停保护
get_more_pages(1,2)

实战:58同城二手平板

设计工作流,分析页面,分析详情……

第一步:得到urls链接

巧用:id = url.split('/')[-1].strip('x.shtml')

fromat函数

构造字典可以这样:
'cate'  '个人' if who_sells == else '商家'    #列表解析式

404检测:if wb_data.status_code == 404:

enumerate() 

核心代码

-----------config.py--------------------
import pymongo
client = pymongo.MongoClient('localhost', 27017)
tongcheng = client['ceshi']
url_list = tongcheng['url_list4']
item_info = tongcheng['item_info4']

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, 
like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'}
-------------参数传递---------------------------
def get_links_from(channel, pages, who_sells='o'):
    # http://bj.ganji.com/ershoubijibendiannao/o3/
    list_view = '{}{}{}/'.format(channel, str(who_sells), str(pages))

-----------多进程------------------------

def get_all_links_from(channel): #新增参数
    for i in range(1,100):
        get_links_from(channel,i)
if __name__ == '__main__':
    pool = Pool()
    # pool = Pool(processes=6)
    pool.map(get_all_links_from,channel_list.split()) #map里面函数没括号
------------数据库计数---------------------
import time
from pages_parsing import url_list #导入数据库
while True:
    print(url_list.find().count())
    time.sleep(5)

--------------断点续传,集合去重-------------
db_urls = [item['url'] for item in url_list.find()]
index_urls = [item['url'] for item in item_info.find()]
x = set(db_urls)
y = set(index_urls)
rest_of_urls = x-y

章节3 第二周:学会爬取大规模数据

Mongdb类似Excel,可见即可得工具,Mongo Explore插件

命名小心关键字啊!!!

爬取大规模大数据流程

思路最重要

1、观察页面特征(不同用户商家男女),编写通用程序 

2、设计工作流程  爬虫一得到列表页url,得到商品链接,爬虫二得到详情页,得到每个商品详情。各司其职。      

3、一页一页向下面解析,不一定全符合规律,小心

代理及404判断

wb_data = requests.get(list_view,headers=headers,proxies=proxies),伪造浏览器,代理ip
----------------------------------    
if wb_data.status_code == 404:
        pass
    else:
        soup = BeautifulSoup(wb_data.text, 'lxml')单进程,

单进程单线程:单人单桌(仅一桌仅一人)        单进程多线程:多人单桌(一桌多人)

多进程单线程:单人多桌(每桌一人)                多进程多线程:吃喜酒(电脑得多核

try函数:出错继续运行

def try_to_make(a_mess):
    try:
        print(1/a_mess)
    except (ZeroDivisionError,TypeError):  #错误代码放这
        print('ok~')
try_to_make(10)

太扯了,一爬就被封ip了,哎

赶集

'pub_date':soup.select('.pr-5')[0].text.strip().split(' ')[0],
# 复杂地区解析
'area':list(map(lambda x:x.text,soup.select('ul.det-infor > li:nth-of-type(3) > a'))),
---------------map函数-------------后面列表迭代
'cates':list(soup.select('ul.det-infor > li:nth-of-type(1) > span')[0].stripped_strings)
---------------字符串--------------

爬虫加速:多核,lxml的xpath快10倍,异步

下一页标签判断是否为最后页

章节4 第三周:数据统计与分析

怎么让数据说话?

1、提出正确问题,正确解释现象(不要结论去验证假设),正确验证假设,幸存者偏差,对比(别人,以前)

2、数据论证,细分,因果关联(脑图,excel)

3、解读数据,数据会说话,数据会说谎,样本偏差

整理清洗数据(删除不要的,整理美观变成我们需要的,重新写入数据库或生成器)

更新数据库

数据可视化

jupyter notebook(不错教程)工具   esc+m 切换模式 tab补全  shift+enter执行代码 

MongoDB导入数据json,安装charts库   开始导入json格式的文件:注意是在CMD目录下, 而不是在客户端shell运行mongoimport命令  shift+回车,执行代码

# 导入数据须知
1. 首先运行 mongo shell在数据库中创建一个 collection —— db.createCollection('your_name')
2. 接下来直接在终端/命令行(cmd)中使用命令导入 json 格式的数据 —— mongoimport -d database_name
-c collection_name path/file_name.json

eg: cmd后直接运行
—— mongoimport -d ceshi -c beijing C:\Users\Administrator\Desktop\fourpython源码\week3\week3_homework\data_sample/sample.json
备份要去bin目录下面

数据边筛选边显示(Highcharts),分析

1、条形图 发帖量

#数据处理
for i in item_info.find():
    if i['area']:
        area = [i for i in i['area'] if i not in punctuation] #非字符串的列表解析
    else:
        area = ['不明']
    item_info.update({'_id':i['_id']},{'$set':{'area':area}}) #更新
-----------------------------------
#列表变集合去重
arealist=[]
for i in item_info.find(): #全部遍历
#     print(i['area'])
    arealist.append(i['area'][0])
    #列表转集合,遍历完成之后
area_index = list(set(arealist))  #去集合重然后再转为列表
print(area_index)
------------------------------------
#统计次数,结合取出的
area_times=[]
for item in area_index:
    area_times.append(arealist.count(item)) #list.count(a) 统计a出现的次数
print(area_times)
妙用生成器,比for快多了
def data_gen(types):
    length = 0
    if length <= len(area_index):
        for area,times in zip(area_index,post_times):
            data = {
                'name':area,
                'data':[times],
                'type':types
            }
            yield data
            length += 1
---------------------------------
series = [data for data in data_gen('column')]

2、折线图 n日内发帖曲线

find函数精确查找数据,强大,不会改变原始数据,具体分片后所有端会显示

-----------日期筛选,地区筛选--------------
for i in item_info.find({'pub_date':{'$in':['2016.01.12','2016.01.14']}},{'area':{'$slice':1},'_id':0,'price':0,'title':0}).limit(300):
    print(i)

1、数据处理

{'pub_date': '2016.01.02'}
{'pub_date': '2016-01-12'}
-----------换成.-------------
for i in item_info.find():
    frags = i['pub_date'].split('-') #有-就分割成列表
    if len(frags) == 1:  #本来就是.的
        date = frags[0]
    else:
        date = '{}.{}.{}'.format(frags[0],frags[1],frags[2])
    item_info.update_one({'_id':i['_id']},{'$set':{'pub_date':date}})

2、让程序明白时间段,获取单日日期

a = date(2015,5,10) 
print(a) #2015-05-10
-----------------
d = timedelta(days=1) #加减
print(d) #1 day, 0:00:00

 

def get_all_dates(date1,date2): #开始及结束时间
    the_date = date(int(date1.split('.')[0]),int(date1.split('.')[1]),int(date1.split('.')[2]))
    end_date = date(int(date2.split('.')[0]),int(date2.split('.')[1]),int(date2.split('.')[2]))
    days = timedelta(days=1) #程序计算时间的

    while the_date <= end_date:
        yield (the_date.strftime('%Y.%m.%d')) #时间格式化
        the_date = the_date + days
---------------------------------------
for i in get_all_dates('2015.12.24','2016.01.05'):
    print(i)
---------------------------------------
2015.12.24
2015.12.25
2015.12.26
2015.12.27
2015.12.28

日期生成器构造

def get_data_within(date1,date2,areas): #地区是传入列表参数
    for area in areas: #获取所有地区循环
        area_day_posts = []
        for date in get_all_dates(date1,date2):
            a = list(item_info.find({'pub_date':date,'area':area}))
            each_day_post = len(a) #每天发帖量
            area_day_posts.append(each_day_post) #装入列表
        data = {
            'name': area,
            'data': area_day_posts,
            'type': 'line'
        }
        yield data
-------------绘图--------------------
options = {
    'chart'   : {'zoomType':'xy'},
    'title'   : {'text': '发帖量统计'},
    'subtitle': {'text': '可视化统计图表'},
    'xAxis'   : {'categories': [i for i in get_all_dates('2015.12.24','2016.01.05')]},
    'yAxis'   : {'title': {'text': '数量'}}
    }

series = [i for i in get_data_within('2015.12.24','2016.01.05',['朝阳','海淀','通州'])]

charts.plot(series, options=options,show='inline')

3、饼图

聚合管道高效查找,管道模型层次筛选,最后输出数据(类似mysql的聚合函数)

已知 求解 所需数据结构

#强大的水管过滤,数据筛选
pipeline = [
    {'$match':{'$and':[{'pub_date':'2015.12.24'},{'time':3}]}}, #匹配日期且(and)时间为3天        
    {'$group':{'_id':'$price','counts':{'$sum':1}}}, #按照price分组,效率高
    {'$sort' :{'counts':-1}}, #以频次分组,倒序排    
    {'$limit':10} #限制
]
# {'pub_date':'2015.12.24'}
--------------------------------------
for i in item_info.aggregate(pipeline): #调用
    print(i)
-------------生成器--------------------
def data_gen(date,time):
    pipeline = [
    {'$match':{'$and':[{'pub_date':date},{'time':time}]}},
    {'$group':{'_id':{'$slice':['$cates',2,1]},'counts':{'$sum':1}}},
    {'$sort':{'counts':-1}}
]
    for i in item_info.aggregate(pipeline):
        yield [i['_id'][0],i['counts']]
--------------构造绘图结果---------------
series =  [{
    'type': 'pie',
    'name': 'pie charts',
    'data':[i for i in data_gen('2016.01.10',1)]

        }]

 

Python Charts库的使用

charts库实际是对调用Highcharts API 进行封装,通过python生成Highcharts脚本

show = 'inline',如果没有这个选项,会开启新标签页面

可以在serie中指定color颜色,type显示的形式(column:柱状图,bar:横向柱状图,line:曲线,area:范围,spline:曲线,scatter:点状,pie:饼状图)

章节5 第四周:搭建 Django 数据可视化网站

以前忽略了,这个需要重点学习

 

创建流程:

  1. 建立虚拟环境(pycharm)
  2. 创建项目
  3. 总设置里面添加应用(app)  python manage.py startapp django_web
  4. 添加模板,templates里面建新文件
  5. 在view里面调用视图函数
  6. urls里面分配网址(正则模糊匹配),先引入库
  7. 运行服务,python manage.py runserver,修改后重新启动
  8. 访问正确网址
  9. static文件位置放对,根目录,引用样式,获取静态文件,修改总设置 {% %}类似format函数
  10. STATICFILES_DIRS=(os.path.join(BASE_DIR,'static'),) #绝对路径加相对文件夹

模板语言

  1. 理解上下文  render函数,模板填空content,content(字典结构)就是数据库取出来替换,原文改造 {{ }}
  2. model,数据结构
  3. 分页工具(数据分页加载) ojects[:4]  每页4条数据 Paginator
  4. Semantic UI 模板框架  

  5. Semantic UI  Gird布局 ,jQuery生成图表

  6. 模板继承(继承图表),也是字典传递数据,view层写以前图表代码
  7. pymongo来操作MongoDB数据库,但是直接把对于数据库的操作代码都写在脚本中,这会让应用的代码耦合性太强,而且不利于代码的优化管理,一般应用都是使用MVC框架来设计的,为了更好地维持MVC结构,需要把数据库操作部分作为model抽离出来,这就需要借助MongoEngine

    MongoEngine是一个对象文档映射器(ODM),相当于一个基于SQL的对象关系映射器(ORM),MongoEngine提供的抽象是基于类的,创建的所有模型都是类,说白了更简单

静态替换:{% %}, 数据库取动态替换{{ }}

完结打卡!!!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值