【1.我为什么选择以爬虫入门python】

首先python开发爬虫的优越性我自不多说,对于深受C++语法折磨的初级程序员来说,想要快速实现功能,选择python妥妥的。同时python的爬虫库也是非常便利(除了安装库时稍费点事),如Scrapy、urllib 。但为了实现功能的同时,顺便熟悉Python语言,这里我们用基本的request+beautifulsoap来编写爬虫。

【2.request是什么,beautifulsoap又是什么】

结合今天要讲的爬虫,就两句话解释(具体请自行百度微笑):

request:能够解析绝大部分http的请求

beautifulsoap:提供丰富的库函数支持你从网页抓取数据

【3.开发环境】

本文中的开发环境是linux,python包是python3.5。(安装的方法请自行百度微笑

【4.简易爬虫的开发思路】

简易的爬虫分为三个部分:

第一,创建连接,登录,有些网站需要你伪装成浏览器登录,并将第一个url放入待抓取的队列。

第二,扫描网页,解析并抓取数据,根据你的需要,将不同的数据放入到不同的已抓取队列中。循环往复,注意判断抓取到的数据是否已经在队列中存在,避免重复抓取。

第三,处理队列中的数据,如下载图片,存日志等,(该步骤可以放在第二步中,如果爬大站点,这样做会让你实时看到抓取的数据,但同时也会影响爬虫的效率。)

大概的思路很简单易懂,自己做的话封函数可能会稍稍费点事。

【5.爬虫中涉及到的几个小点】

这部分是写给初学者看的,对于一些未接触过的库和api,这里写了几个小demo进行测试,毕竟没有测过直接整合到一起,到最后疯狂的报错会让人抓狂。

5.1 日志模块

python有一些让我很疑惑的地方,也希望又看到的朋友帮忙解答:

槽点!!!为什么有些模块,单个入参很简单,多个入参的时候却显得有些繁琐。日志模块就是其中之一。

当你的程序中只有一个日志输出的时候。可以直接定义如下:

import logging

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                    datefmt='%m-%d %H:%M',
                    filename='myapp.log',
                    filemode='w'
                    )

定义日志的输出格式,内容,级别,名字和读写权限。

定义多个日志输出时,这种方法就不适用了,代码如下:

import logging
#import requests
#import os
def logtest():
    # 创建一个logger
    logger = logging.getLogger('mylogger')
    logger.setLevel(logging.DEBUG)
    # 创建一个handler,用于写入日志文件
    fh = logging.FileHandler('test.log')
    fh.setLevel(logging.DEBUG)
    # 创建一个handler,用于写入日志文件
    fh1 = logging.FileHandler('test1.log')
    fh1.setLevel(logging.DEBUG)
    # 再创建一个handler,用于输出到控制台
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    # 定义handler的输出格式
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    fh1.setFormatter(formatter)
    ch.setFormatter(formatter)
    # 给logger添加handler
    logger.addHandler(fh1)
    logger.addHandler(fh)
    logger.addHandler(ch)
    # 记录一条日志
    logger.info('foorbar')

5.2 下载网络图片到本地
这里主要是要利用os设置文件的路径,同时这里添加了判断是否已存在该文件路径。
import logging
import requests
import os
mysession = requests.session()
myrequests = mysession.get(url)
picDir = os.path.abspath('.')
picDir = os.path.join(picDir, 'picDir')
if not os.path.exists(picDir):
    os.mkdir(picDir)
print(picDir)
picno = 1
filename = os.path.join(picDir +'/' + str(picno) + '.jpg')
print(filename)
with open(filename, 'wb') as code:
    code.write(myrequests.content)

5.3 线程池
如果有兴趣,可以尝试一下,使用线程池和不使用线程池的差别。
import threadpool
import random

def hello(n):
    print(n)
data = [ random.randint(1, 10) for i in range(20) ]
g_threadPool = threadpool.ThreadPool(10)
#python2 is xrange, python3 is range
#for i in range(1,10):
param = [data]
requests = threadpool.makeRequests(hello, param)    
[ g_threadPool.putRequest(req) for req in requests ]    
g_threadPool.wait()   

(由于多参数的情况还没研究出来,搞得没耐心了,就直接用for循环创造线程了难过

5.4 beautifulsoap测试


from bs4 import BeautifulSoup
import requests
import logging

#定义线程爬取网址
logging.info('开始爬虫了')
#建立一个永久会话
my_session = requests.session()
#定义初始网址
initial_page = "http://wufazhuce.com/one/1293"
#定义一个伪装成浏览器的头
my_header = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0"
#使用get方法发生请求,post方式可以添加header伪装登录方式
try:
    result_get = my_session.get(initial_page)
except:
    print("这个网址访问异常==============" + current_url)

try:
    soup = BeautifulSoup(result_get.text, "html.parser")
except :
            print("构建beautifulSoup失败===========" + initial_page)

Soup_f_b = soup.find('body')
if Soup_f_b == None:
    logging.info("该Url没有body属性============" + current_url)

#list_img = Soup_f_b.findAll('img', attr = {'src',True})
list_img = Soup_f_b.select("img[alt]")
for meta in list_img:
    print(meta.get('src'))
#url_list = Soup_f_b.findAll('a', attrs = {'href':True})
#url_list = Soup_f_b.select("a")
#for meta in url_list:
#    print(meta.get('href'))
#print(url_list)
#name_list = soup.select("meta[itemprop='description']")
#name_content = name_list[0].get('content')
#for meta in Soup_f_b.select('meta'):
#    if meta.get('name') == 'description':
#print(name_content)
print(soup.title)

本次程序爬行的是ONE,测试结果如下所示:



【6.几个注意事项】
其实把上面的几个demo凑在一起,爬虫的大致框架就出来了,但有几点需要注意一下:
1.在使用多线程的时候,注意在操作队列时,要加锁,防止多线程同时写操作。
2.注意python2.x和python3.x的区别,类似SyntaxError: invalid syntax,这种错误可能是版本差别引起。

【说在最后】
第一个版本详细代码我会放在github上,会持续修补,地址稍后补上。
对于文章提到的吐槽点,也请各位看到的朋友,帮忙解答,不胜感激。
运行效率上我还没有做优化,因此后续也希望各位牛人提供宝贵意见。
---------------------------------------------------------更新20171006---------------------------------------------------------
代码位置:https://github.com/BinaryTreeNode/mylittlespyder








GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐