当前位置: 亚洲城ca88 > ca88 > 正文

我的第一个python爬虫,Python开发爬虫之理论篇

时间:2019-05-18 00:54来源:ca88
我的第一个爬虫,哈哈,纯面向过程 爬虫简介  爬虫:一段自动抓取互联网信息的程序。 什么意思呢? 互联网是由各种各样的网页组成。每一个网页对应一个URL,而URL的页面上又有很

我的第一个爬虫,哈哈,纯面向过程

爬虫简介


 爬虫:一段自动抓取互联网信息的程序。

什么意思呢?

互联网是由各种各样的网页组成。每一个网页对应一个URL,而URL的页面上又有很多指向其他页面的URL。这种URL之间相互的指向关系就形成了一个网络,这就是互联网。

正常情况下就是我们采用人工点击的方式,去获取互联网上指定的信息,这种方式的特点是覆盖面小。

那有没有可能有一种方式,是当我们设定了一个互联网上感兴趣的目标,然后自动地从互联网上去获取我们所需要的数据呢?

有,这就是爬虫。它可以从一个URL出发访问该URL所关联的所有URL,并且从每个页面上提取出我们所需要的价值数据。

图片 1

也就是说,爬虫就是自动访问互联网,并且提取数据的程序。

 

1.概述

对于轻量级爬虫

  • 只抓取静态页面

而对于高级的爬虫,需要考虑的因素就较多,如:

  • 如何模拟登陆
  • 验证码识别
  • 分布式爬取网页
  • 数据存储
  • 网页更新

这些因素都具有重要的现实意义,但是对于初学者来讲,了解爬虫的基础架构显得更为必要,在实际应用场景中对其扩展可以爬取其他网页。

对于一个简单的爬虫架构,它包含了以下三大模块:
<font color=#FF4500>URL管理器:</font> 用来管理将要抓取的URL和已经抓取过的URL
<font color=#FF4500>HTML下载器:</font>给定一个URL,需要将其网页下载到本地后才能进行后续的分析。(这里使用Python自带的urllib2模块)
<font color=#FF4500>HTML解析器:</font>得到了网页的内容以后,我们需要对其进行解析才能提取出我们想要的、我们感兴趣的内容。(这里使用Python的第三方插件BeautifulSoup)


实现目标:

爬虫技术的价值


 互联网数据,为我所用。

 

2.爬虫架构:

<font color=#FF4500>爬虫调度端:</font>
启动爬虫、停止爬虫或者监视爬虫的运行情况

而在爬虫程序中有三个模块:

<font color=#FF4500>URL管理器:</font>对将要抓取的URL和已经抓取过的URL进行管理。我们可以取出一个将要爬取的URL传送给<font color=#FF4500>HTML下载器:</font>,下载器会将URL指定的网页下载下来,存储成一个字符串,这个字符串会传送给<font color=#FF4500>HTML解析器:</font>进行解析,一方面会解析出有价值的数据,另一方面每一个网页会有许多指向其他网页的URL,这些URL被解析出来以后可以补充进URL管理器。
URL管理器、HTML下载器和HTML下载器会形成一个循环,只要有相关联的URL就会一直运行下去。以上这些模块就组成了这个简单的爬虫架构。这个架构就可以把互联网上的相关所有网页下载下来。

图片 2

爬虫架构

爬虫运行流程:
下图以时序图的方式给出了爬虫架构的运行流程

图片 3

简单爬虫架构动态运行流程

  1.抓取本地conf文件,其中的URL地址,然后抓取视频名称以及对应的下载URL

Python简单爬虫架构


图片 4

1)首先,我们需要一个爬虫调度端。爬虫调度端的作用:启动爬虫,停止爬虫,监视爬虫运行情况。

2)在爬虫程序中有三个模块:URL管理器、网页下载器、网页解析器。

3)URL管理器:对将要爬取的和已经爬取过的URL进行管理;可取出待爬取的URL,将其传送给“网页下载器”。

4)网页下载器:将URL指定的网页下载,存储成一个字符串,在传送给“网页解析器”。

5)网页解析器:解析网页可解析出

    ①有价值的数据

    ②另一方面,每个网页都包含有指向其他网页的URL,解析出来后可补充进“URL管理器”

此时,这三个模块就形成了一个循环,只要有感兴趣的URL,这三个模块就会一直循环下去。

 

3.URL管理器

  • URL管理器:管理待抓取URL集合和已抓取URL集合
  • 防止重复抓取、防止循环抓取

URL管理器功能

图片 5

URL管理器功能

Python爬虫URL管理器实现方式

图片 6

URL管理器的实现方式

  2.抓取URL会单独写在本地路径下,以便复制粘贴下载

 Python简单爬虫架构的动态运行流程(以时序图的方式展示)


 

图片 7

 

4.HTML下载器

HTML下载器简介

HTML下载器:将互联网上URL上对应的网页下载到本地的工具。可以说HTML下载器是爬虫的核心组件

图片 8

HTML下载器

  • Python有哪几种网页下载器?

  • <font color=#FF4500>urllib2</font>是Python官方的基础模块,支持直接的URL下载,或者向网页提供需要用户输入的数据,甚至支持需要登录网页的cookie处理,需要代理访问的代理处理等这些增强功能

  • <font color=#FF4500>requests</font>是Python的第三方插件,它提供更为强大的功能

图片 9

HTML下载器分类

这里使用urllib2.

urllib2下载网页的三种方法

1.最简洁方法

给定一个url,将其传送给urllib2模块的urlopen()方法,即:urllib2.urlopen(url)
对应到代码:

import urllib2

# 直接请求
response=urllib2.urlopen('http://www.baidu.com') 

# 获取状态码,如果是200表示获取成功
print response.getcode()

# 读取内容
cont=response.read()```


**2.添加data、http header**
![方法2](http://upload-images.jianshu.io/upload_images/3480470-7cdf6be81b2e6df3.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)

对应到代码:

import urllib2

废话补多少,代码实现效果如下:

 Python爬虫URL管理


 URL管理器:管理待抓取URL集合和已抓取URL集合。

目的:防止重复抓取、防止循环抓取。

图片 10

 

创建Request对象

request=urllib2.Request(url)

图片 11

Python爬虫URL管理器的实现方式


 Python爬虫URL管理器的实现方式具体有三种:

1)使用内存,在Python中主要使用set集合(方便去除重复的元素)

图片 12

2)使用关系数据库,使用两个字段:url和is_crawled(用来标记是否被爬取)

图片 13

3)使用缓存数据库,同样使用set集合

图片 14

其中,大型公司一般选择高性能的缓存数据库。个人,小公司一般使用内存。若是想永久存储,常使用关系数据库。

 

添加data

request.add_data('a','1')

 

Python爬虫网页下载器简介


图片 15

网页下载器:一个工具,通过URL将互联网上对应的的网页以HTML的形式下载到本地存储成本地文件或内存字符串,后进行后续处理;

Python有哪几种网页下载器:urllib2(Python官方模块,基础模块)、requests(第三方模块,功能强大)。

 

添加http的header

request.add_header('User-Agent','Mozilla/5.0')

代码如下:

Python爬虫urlib2下载器网页的三种方法


 1)urllib2下载网页方法1:最简洁方法

将url直接传给urllib2的urlopen()方法。

图片 16

对应代码:

图片 17

 

2)urllib2下载网页方法2:除url外,添加data、http header。

进行增强处理。

其中,data向服务器提交需要用户输入的数据。

http header用来向服务器提交http的头信息。

图片 18

对应代码:

图片 19

代码中request.add_data('a','1')  #添加的数据类型为键值对,即a=1。

request.add_header()  #可以对url请求进行伪装

 

3)urllib2下载网页方法3:添加特殊情景的处理器

更大更强的功能处理能力。

图片 20

对应代码(举例:增强cookie的处理)

图片 21

 

发送请求获取结果

response=urllib2.urlopen(request)```

3.添加特殊情景的处理器

图片 22

特殊情景处理器

例如,增强cookie的处理,对应到代码:

import urllib2,cookielib

# 创建cookie容器
cj=cookielib.CookieJar()

# 创建一个opener
opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))

# 给urllib2安装opener
urllib2.install_opener(opener)

# 使用带有cookie的urllib2访问网页
reponse=urllib2.urlopen("http://www.baidu.com/")```

以上三种方法都实现了网页的下载,但是每一种方法都比前一种方法有更大的更强的功能处理。


### 5.HTML解析器和BeautifulSoup第三方模块

>#### HTML解析器

HTML解析器:从网页中提取有价值数据的工具
![网页解析器](http://upload-images.jianshu.io/upload_images/3480470-21afe8826281ba9b.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)


Python有哪几种HTML解析器?

![HTML解析器分类](http://upload-images.jianshu.io/upload_images/3480470-ab5a1e42c60da28a.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)

- **结构化解析-DOM(Document Object Model)树**
![DOM树.png](http://upload-images.jianshu.io/upload_images/3480470-e5138777c3844bb9.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)

>#### Beautiful Soup

 - Python第三方库,用于从HTML或XML中提取数据
 - 官网:http://www.crummy.com/software/BeautifulSoup/


- 安装并测试beautifulsoup4
 - 安装:pip install beautifulsoup4
 - 测试:import bs4

- Beautiful Soup-语法
![Beautiful Soup-语法](http://upload-images.jianshu.io/upload_images/3480470-cbdbe787de89ceb1.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)

例如:
![举例](http://upload-images.jianshu.io/upload_images/3480470-b8106c578b037fea.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)

对应到代码:
- 创建BeautifulSoup对象

form bs4 import BeautifulSoup

  1 #!/usr/local/python/bin/python3
  2 
  3 import requests
  4 import re
  5 import chardet
  6 import random
  7 import signal
  8 import time
  9 import os
 10 import sys
 11 
 12 def DealwithURL(url):
 13     r = requests.get(url)
 14     pattern = re.compile('<meta http-equiv="refresh" content="0.1;url=')
 15     findurl=re.findall(pattern,r.text)
 16 
 17     if findurl:
 18         pattern = re.compile('<meta http-equiv="refresh" content="0.1;url=(.*)"')
 19 
 20         transferurl = re.findall(pattern,r.text)[0]
 21 
 22         return transferurl
 23     else :
 24         return True
 25 
 26 def GetNewURL(url):
 27     r = requests.get(url)
 28 
 29     r.encoding='utf-8'
 30     pattern = re.compile('alert(.*)">')
 31     findurl=re.findall(pattern,r.text)
 32     findurl_str = (" ".join(findurl))
 33     return (findurl_str.split(' ',1)[0][2:])
 34 
 35 def gettrueurl(url):
 36     if DealwithURL(url)==True:
 37         return url
 38     else :
 39         return GetNewURL(DealwithURL(url))
 40 
 41 def SaveLocalUrl(untreatedurl,treatedurl):
 42     if untreatedurl == treatedurl :
 43         pass
 44     else :
 45         try:
 46             fileconf = open(r'main.conf','r')
 47             rewritestr = ""
 48             
 49             for readline in fileconf:
 50                 if re.search(untreatedurl,readline):
 51                     readline = re.sub(untreatedurl,treatedurl,readline)
 52                     rewritestr = rewritestr   readline
 53                 else :
 54                     rewritestr = rewritestr   readline
 55             fileconf.close()
 56             
 57             fileconf = open(r'main.conf','w')
 58             fileconf.write(rewritestr)
 59             fileconf.close()
 60             
 61         except:
 62             print ("get new url but open files ng write to logs")
 63 
 64 def handler(signum,frame):
 65     raise AssertionError
 66 
 67 def WriteLocalDownloadURL(downfile,downurled2k):
 68     urlfile = open(downfile,'a ')
 69     
 70     urlfile.write(downurled2k 'n')
 71             
 72 def GetDownloadURL(sourceurl,titleurl,titlename,update_file,headers):
 73     downurlstr = (" ".join(titleurl))
 74     downnamestr = (" ".join(titlename))
 75 
 76     r = requests.get((sourceurl downurlstr),headers)
 77     pattern = re.compile('autocomplete="on">(.*)/</textarea></div>')
 78 
 79     downurled2k = re.findall(pattern,r.text)
 80     downurled2kstr = (" ".join(downurled2k))
 81 
 82     WriteLocalDownloadURL(update_file , downurled2kstr)
 83 
 84     print (downnamestr , downurled2kstr)
 85 
 86 
 87 def ReadLocalFiles() :
 88     returndict={}
 89     localfiles = open(r'main.conf')
 90     
 91     readline = localfiles.readline().rstrip()
 92 
 93     while readline :
 94         if readline.startswith('#'):
 95             pass
 96         else:
 97             try:
 98                 readline = readline.rstrip()
 99                 returndict[readline.split('=')[0]] = readline.split('=')[1]
100             except:
101                 print ("Please Check your conf %s" %(readline))
102                 sys.exit(1)
103         readline = localfiles.readline().rstrip()
104 
105     localfiles.close()
106     return returndict
107 
108 
109 def GetListURLinfo(sourceurl , title , getpagenumber , total,update_file,headers):
110     
111     if total >= 100:
112         total = 100
113 
114     if total <= 1:
115         total = 2
116     
117     getpagenumber = total
118         
119     for number in range(0,total) :
120         try:
121             signal.signal(signal.SIGALRM,handler)
122             signal.alarm(3)
123         
124     
125             url = sourceurl   title   '-'   str(random.randint(1,getpagenumber))   '.html'
126 
127             r = requests.get(url,headers)
128 
129             pattern = re.compile('<div class="info"><h2>(.*)</a><em></em></h2>')
130             r.encoding = chardet.detect(r.content)['encoding']
131             allurl = re.findall(pattern,r.text)
132 
133 
134             for lineurl in allurl:
135                 try:
136                     signal.signal(signal.SIGALRM,handler)
137                     signal.alarm(3)
138 
139                     pattern = re.compile('<a href="(.*)" title')
140                     titleurl = re.findall(pattern,lineurl)
141         
142                     pattern = re.compile('title="(.*)" target=')
143                     titlename = re.findall(pattern,lineurl)
144 
145                     GetDownloadURL(sourceurl,titleurl,titlename,update_file,headers)
146                     signal.alarm(0)
147                 except AssertionError:
148                     print (lineurl,titlename , "Timeout Error: the cmd 10s have not finished")            
149                     continue
150 
151 #            title = '/list/' str(random.randint(1,8))
152 #            print (title)
153 #            print (title_header)
154 
155         except AssertionError:
156             print ("GetlistURL Infor Error")            
157             continue
158 
159 def GetTitleInfo(url,down_page,update_file,headers):
160     
161     title = '/list/' str(random.randint(1,8))
162     
163     titleurl = url   title   '.html'
164 
165     r = requests.get(titleurl,headers)
166     r.encoding = chardet.detect(r.content)['encoding']
167     pattern = re.compile('&nbsp;当前:.*/(.*)页&nbsp;')
168     getpagenumber = re.findall(pattern,r.text)
169     
170     getpagenumber = (" ".join(getpagenumber))
171 
172     GetListURLinfo(url , title , int(getpagenumber) , int(down_page),update_file,headers)
173 
174     
175 def write_logs(time,logs):
176     loginfo = str(time) logs
177     try:
178         logfile = open(r'logs','a ')
179         logfile.write(loginfo)
180         logfile.close()
181     except:
182         print ("Write logs error,code:154")
183     
184 
185 def DeleteHisFiles(update_file):
186     if os.path.isfile(update_file):
187         try:
188             download_files = open(update_file,'r ')
189             download_files.truncate()
190             download_files.close()
191         except:
192             print ("Delete "   update_file   "Error --code:166")
193     else :
194         print ("Build New downfiles")
195     
196 def main():
197     headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit 537.36 (KHTML, like Gecko) Chrome","Accept": "text/html,application/xhtml xml,application/xml; q=0.9,image/webp,*/*;q=0.8"}
198 
199     readconf = ReadLocalFiles()
200     
201     try:
202         file_url = readconf['url']
203         down_page = readconf['download_page']
204         update_file = readconf['download_local_files']
205     except:
206         print ("Get local conf error,please check it")    
207         sys.exit(-1)
208 
209     DeleteHisFiles(update_file)
210 
211     untreatedurl = file_url
212     
213     treatedurl = gettrueurl(untreatedurl)
214     SaveLocalUrl(untreatedurl,treatedurl)
215 
216     url = treatedurl
217     
218     GetTitleInfo(url,int(down_page),update_file,headers)
219 
220 
221 if __name__=="__main__":
222     main()

Python爬虫urlib2实例代码演示


import urllib2, cookielib

url ="http://www.baidu.com"

print '第一种方法'
respones1 = urllib2.urlopen(url)
print respones1.getcode()
print len(respones1.read())

print "第二种方法"
request = urllib2.Request(url)
request.add_header("user-agent","Mozillla/5.0")
respones2 = urllib2.urlopen(request)
print respones2.getcode()
print len(respones2.read())

print '第三种方法'
cj =cookielib.CookieJar()
opener = urllib2.bulid_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)
print respones3.getcode()
print cj
print respones3.read()

 

根据HTML网页字符串创建BeautifulSoup对象

soup=BeautifulSoup(
html_doc, #HTML文档字符串
'html.paser' #HTML解析器
from_encoding='utf8' #HTML文档的编码
)```

  • 搜索节点(find_all,find)
# 方法:find_all(name,attrs,string)

# 查找所有标签为a的节点
soup.find_all('a')

# 查找所有标签为a,链接符合/view/123.htm形式的节点
soup.find_all('a',href='/view/123.htm')
soup.find_all('a',href=re.compile(r'/view/d .htm'))

# 查找所有标签为div,class为abc,文字为Python的节点
soup.find_all('div',class_='abc',string='Python')```

- 访问节点信息

 对应的main.conf如下:

Python爬虫网页解析器简介


 

网页解析器:从网页中提取有价值数据的工具。

功能:

1)提取出新的待爬取URL列表;

2)解析出有价值的数据:

网页解析器会以下载好的html网页字符串作为输入,提取出有价值的数据以及新的待爬取的URL列表。

图片 23

Python有哪些网页解析器呢?

1)正则表达式。最直观的一种。将网页文档down成一个字符串,采用模糊匹配的方式进行提取有价值的数据。虽然直观,但是当网页文档十分复杂的时候,这种方式将十分复杂。

2)使用Python自带的html.parser模块进行解析。

3)使用Beautiful Soup这个第三方插件来解析网页。功能强大的Beautiful Soup可以用html.parser或者lxml作为它的解析器。

4)使用lxml这个第三方插件来解析html网页或者xml文档。

图片 24

结构化解析——DOM(DOcument Object Model)树

 

得到结点:<a href='1.html'> Python </a>

图片 25

BeautifulSoup第三方模块


BeautifulSoup官网:

安装BeautifulSoup:

如果你安装了pip,那么就简单了,无需从官网下载,打开命令提示符页面。

进入到Python安装目录下的Scripts文件夹路径下,输入“pip install beautifulsoup4”,即可进行自动安装。

图片 26

安装完,在eclipse中进行测试,新建一个Python模块,输入:

import bs4
print bs4

输出为:

图片 27

证明安装成功。

 

获取查找到的节点的标签名称

node.name

本着对爬虫的好奇来写下这些代码,如有对代码感兴趣的,可以私聊提供完整的conf信息,毕竟,我也是做运维的,要脸,从不用服务器下片。

BeautifulSoup的语法


 图片 28

其中搜索节点的find_all()方法可以搜索出所有符合要求的节点,而find()方法则只是搜索出符合条件的第一个节点。但是两个函数的参数是完全相同的。

图片 29

对应代码:

1)创建BeautifulSoup对象

图片 30

2)搜索节点(find_all、find)

图片 31

其中红色部分为正则表达式形式。

最后一句之所以"class_"要加上下划线是因为要和Python的关键字"class"进行区分。

3)访问节点信息

图片 32

4)BeautifulSoup的实例测试

# coding:utf-8
from bs4 import BeautifulSoup
import re
print("Python3 的代码如下")
html_doc = """
因字数限制,省略。请到 http://www.crummy.com/software/BeautifulSoup/bs4/doc/#searching-the-tree 复制吧
"""

soup = BeautifulSoup(html_doc, 'html.parser')
print("获取所有的链接")
links = soup.find_all('a')
for link in links:
 print(link.name, link['href'], link.get_text())

print("获取lacie的链接")
link_node = soup.find('a', href="http://example.com/lacie")
print(link_node.name, link_node['href'], link_node.get_text())
print("正则匹配")
link_node = soup.find('a', href=re.compile(r"ill"))
print(link_node.name, link_node['href'], link_node.get_text())

print("获取p段落文字")
p_node = soup.find('p', class_="title")
print(p_node.name, p_node.get_text())

 

获取查找到的a结点的href属性

node['href']

 

实战演练:爬取百度百科1000个页面的数据


1) 实例爬虫操作步骤

图片 33

2)Python爬虫实例-分析目标

图片 34

 

 

 

 

 

 

 本篇博客参考慕课网课程:

 

获取 查找到的a结点的链接文字

node.get_text()```

** 通过以上创建BS对象、搜索DOM树、访问节点的内容,就可以实现对整个下载好的网页所有节点的解析、访问。**

6.实例

这里爬取的是百度百科Python词条相关的1000个页面数据,(本实例来源于慕课网教程)。
然后将这些数据写出到一个HTML5页面中,打开这个页面就可以看到我们已经爬取好的数据。
代码我已经敲了一遍,在Python3 版本亲测可执行,可以在我的GitHub获取。
爬取结果如下图:

图片 35

编辑:ca88 本文来源:我的第一个python爬虫,Python开发爬虫之理论篇

关键词: 亚洲城ca88