用python进行网络爬虫(三)—— 数据抓取
在上两篇
用python进行网络爬虫(一)—— 编写第一个爬虫
我们构建了一个爬虫,但是却不够实用,因为爬虫在下载网页后就将结果丢弃了。
用python进行网络爬虫(二)快速上手——requests
我们能获取网页内容,但是获取整个网页却未必是我们需要的,因为大多数情况我们只想要网页里的某些元素。
现在我们需要从每个网页中抽取一些数据,然后实现某些事情,这个也称为 抓取 。
文章目录
- 数据类型
- 一、半结构化数据
- json数据
- XML
- 二、非结构化数据
- 处理方式
- Python3 JSON 数据解析
- 案例
- 实现步骤
- 代码实现
- 分析网页
- 抓取网页方法
- 1、正则表达式
- 特点
- re模块的使用过程
- 正则表达式示例
- 正则表达式常见语法
- 示例1:匹配单个字符
- 匹配多个字符
- 常用的正则表达式:
- re.search方法
- 2、Beautiful Soup
- 例子
- 安装解析器
- 如何使用
- 对象的种类
- Tag
- Name
- Attributes
- beautifulsoup使用
- 3、lxml
- 使用控制台
- xpath 选择器
- 选择节点的基本规则
- xpath的谓语条件(Predicate)
- 通配符
- 抓取结果
- 总结
- 参考
数据类型
一、半结构化数据
半结构化数据是结构化数据的一种形式,它并不符合关系型数据库或其他数据表的形式关联起来的数据模型结构,但包含相关标记,用来分隔语义元素以及对记录和字段进行分层。因此,它也被称为自描述的结构。
常见的半结构数据有JSON、XML。
json数据
JSON 是存储和交换文本信息的语法。类似 XML。结构类似于python字典
JSON易于人阅读和编写。同时也易于机器解析和生成。
JSON 比 XML 更小、更快,更易解析。
- JSON 实例
{"name":"张三","age":32,"parents":{"mother":"m","father":"f"}
}
- 处理方式
通过 json 模块等直接转成 Python 数据类型
json.loads #json字符串 转 Python数据类型
json.dumps #Python数据类型 转 json字符串
json.load #json文件 转 Python数据类型
json.dump #Python数据类型 转 json文件
例子:
import json
# Python 字典类型转换为 JSON 对象
data = {'no' : 1,'name' : 'Runoob','url' : 'http://www.runoob.com'
}json_str = json.dumps(data)
print ("Python 原始数据:", repr(data))
print ("JSON 对象:", json_str)
执行以上代码输出结果为:
Python 原始数据: {'url': 'http://www.runoob.com', 'no': 1, 'name': 'Runoob'}
JSON 对象: {"url": "http://www.runoob.com", "no": 1, "name": "Runoob"}
XML
XML 指可扩展标记语言(eXtensible Markup Language)。
XML 被设计用来传输和存储数据。
XML 很重要,也很容易学习。
- XML 文档实例
<?xml version="1.0" encoding="UTF-8"?>
<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body>
</note>
上面的这条便签具有自我描述性。它包含了发送者和接受者的信息,同时拥有标题以及消息主体。
但是,这个 XML 文档仍然没有做任何事情。它仅仅是包装在 XML 标签中的纯粹的信息。我们需要编写软件或者程序,才能传送、接收和显示出这个文档。
- XML 指可扩展标记语言(EXtensible Markup Language)。
- XML 是一种很像HTML的标记语言。
- XML 的设计宗旨是传输数据,而不是显示数据。
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
二、非结构化数据
非结构化数据是数据结构不规则或不完整,没有预定义的数据模型,不方便用数据库二维逻辑表来表现的数据。包括所有格式的办公文档、文本、图片、各类报表、图像和音频/视频信息等等。
所以非结构化数据非常多样,难以标准化。
处理方式
通过 正则表达式 、 xpath 、beautifulsoup
等模块提取数据
Python3 JSON 数据解析
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。
Python3 中可以使用 json 模块来对 JSON 数据进行编解码,主要使用两个函数:
json.dumps(): 对数据进行编码。
json.loads(): 对数据进行解码。
Python 编码为 JSON 类型转换对应表:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | true |
False | false |
None | null |
JSON 解码为 Python 类型转换对应表:
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
案例
从 http://www.lagou.com/lbs/getAllCitySearchLabels.json 接口返回数据中提取所有的城市信息
实现步骤
- 网络获取数据
- 把响应数据转换成python数据类型
- 从中提取数据
代码实现
# 获取数据
import requests
import json
import jsonpathurl = "http://www.lagou.com/lbs/getAllCitySearchLabels.json"
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
}response = requests.get(url,headers=headers)
html = response.text
#print(html)
# 把响应数据转换成python数据类型
data = json.loads(html)# 使用 jsonpath 提取数据
cities = jsonpath.jsonpath(data,'$..name')
print(cities)
当然你也可以不用第三方库,自行手动提取,只需把最后两行代码更改为:
#根据json结构手动解析
#{"state":1,"message":"success","content":{"data":{"allCitySearchLabels":{"A":[{"id":723,"name":"安阳","parentId":545,"code":"171500000","isSelected":false}
for alpha in data['content']['data']["allCitySearchLabels"].keys():for i in range(len(data['content']['data']["allCitySearchLabels"][alpha])):print((data['content']['data']["allCitySearchLabels"][alpha][i]['name']),end='、')
分析网页
要理解一个网页结构如何,可以使用查看网页源代码(view page source)的方法。一般来说大多数浏览器,在网页中右键鼠标就可以看到这个选项。不过这样有时候并不适合阅读。我们可以选择检查元素来查看:
抓取网页方法
1、正则表达式
正则表达式就是记录文本规则的代码
特点
正则表达式的语法很令人头疼,可读性差
正则表达式通用行很强,能够适用于很多编程语言
正则表达式用起来比较复杂,如果不熟悉的话,建议先系统的学习一下正则表达式的用法。
re模块的使用过程
在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用一个模块,名字为re
# 导入re模块
import re# 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
正则表达式示例
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
import reresult = re.match('hel*',"hello.cn")print(result.group())
hel* 表示匹配he加上任意个 l 的字符,如 hel,hell,helllll
结果:
hell
正则表达式常见语法
- 字符
语法 | 说明 | 表达式案例 | 完整匹配字符串 |
---|---|---|---|
一般字符 | 匹配自身 | abc | abc |
. |
匹配任意除换行符\n 外的字符。在DOTALL模式中也能匹配换行符
|
a.c | abc |
\ | 转义字符,使后一个字符表示字符本身。 | a.c | a.c |
[…] | 选取字符范围 | a[bcd]e | abe 或 ace 或 ade |
- 预定义字符集(可以写在字符集[…]中)
语法 | 说明 | 表达式案例 | 完整匹配字符串 |
---|---|---|---|
\d | 数字:[0-9] | a\dc | a1c、a5c、····· |
\D | 非数字:[^0-9] | a\Dc | abc ,afc、···· |
\s | 空白字符:[<空格>\t\r\n\f\v] | a\sc | a c |
\S | 非空白字符:[^<空格>\t\r\n\f\v] | a\Sc | abc 、a-c、a$c、··· |
\w | 单词字符:[A-Za-z0-9_] | a\wc | abc |
\W | 非单词字符:[^A-Za-z0-9_] | a\Wc | a c |
- 数量词(用在字符或(…)之后)
语法 | 说明 | 表达式案例 | 完整匹配字符串 |
---|---|---|---|
* | 匹配前一个字符0次或无限次。 | abc* | ab 、abc、abcc、abccc····· |
+ | 匹配前一个字符1次或无限次。 | abc+ | abc、abcc、abccc····· |
? | 匹配前一个字符0次或1次。 | abc? | abc 或 ab |
{m} | 匹配前一个字符m次。 | ab{2}c | abbc |
示例1:匹配单个字符
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
#coding=utf-8import reret = re.match(".","M")
print(ret.group())ret = re.match("t.o","too")
print(ret.group())
运行结果:
M
too
匹配多个字符
import reline = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
#第三个参数是标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配
if matchObj:print ("matchObj.group() : ", matchObj.group())print ("matchObj.group(1) : ", matchObj.group(1))print ("matchObj.group(2) : ", matchObj.group(2))
else:print ("No match!!")
结果:
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter
常用的正则表达式:
1 Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
2 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
3 InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
4 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
5 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
6 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
7 身份证号:
15或18位身份证:^\d{15}|\d{18}$
15位身份证:^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$
18位身份证:^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$
8 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
9 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
10 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
11 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
12 日期格式:^\d{4}-\d{1,2}-\d{1,2}
re.search方法
re.search 扫描整个字符串并返回第一个成功的匹配。
import reprint(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配
以上实例运行输出结果为:
(0, 3)
(11, 14)
2、Beautiful Soup
Beautiful Soup是一个非常流行的python库,它可以解析网页,并提供了定位内容的便捷接口:
安装:
pip install beautifulsoup4
使用beautiful soup的第一步是将已下载的HTML内容解析为soup文档。
例子
用bs解释下面这个未正确闭合的标签:
from bs4 import BeautifulSoupboken_html ='<ul class=country> <li> Area </ul>'
soup = BeautifulSoup(boken_html)
print(soup.prettify())
<html><body><ul class="country"><li>Area</li></ul></body>
</html>
可以看到已经变成了完整且正确的html文档。
print(soup('li'))
[<li> Area </li>]
安装解析器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml .
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(markup, “html.parser”) |
Python的内置标准库 执行速度适中 文档容错能力强 |
Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup, “lxml”) |
速度快 文档容错能力强 |
需要安装C语言库 |
lxml XML 解析器 |
BeautifulSoup(markup, [“lxml-xml”]) BeautifulSoup(markup, “xml”) |
速度快 唯一支持XML的解析器 |
需要安装C语言库 |
html5lib | BeautifulSoup(markup, “html5lib”) |
最好的容错性 以浏览器的方式解析文档 生成HTML5格式的文档 |
速度慢 不依赖外部扩展 |
推荐使用lxml作为解析器,因为效率更高.
在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib, 因为那些Python版本的标准库中内置的HTML解析方法不够稳定.
如何使用
将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄.
from bs4 import BeautifulSoupsoup = BeautifulSoup(open("index.html"))soup = BeautifulSoup("<html>data</html>")
首先,文档被转换成Unicode,并且HTML的实例都被转换成Unicode编码
BeautifulSoup("Sacré bleu!")
<html><head></head><body>Sacré bleu!</body></html>
然后,Beautiful Soup选择最合适的解析器来解析这段文档,如果手动指定解析器那么Beautiful Soup会选择指定的解析器来解析文档.
对象的种类
Beautiful Soup 将复杂 HTML 文档转换成一个复杂的树形结构,每个节点都是 Python 对象,所有对象可以归纳为 4 种: Tag , NavigableString , BeautifulSoup , Comment .
- Tag:通俗点讲就是 HTML 中的一个个标签,像上面的 div,p。每个 Tag 有两个重要的属性 name 和 attrs,name 指标签的名字或者 tag 本身的 name,attrs 通常指一个标签的 class。
- NavigableString:获取标签内部的文字,如,soup.p.string。
- BeautifulSoup:表示一个文档的全部内容。
- Comment:Comment 对象是一个特殊类型的 NavigableString 对象,其输出的内容不包括注释符号.
Tag
Tag 对象与XML或HTML原生文档中的tag相同:
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')
tag = soup.b
type(tag)
# <class 'bs4.element.Tag'>
Tag有很多方法和属性,在 遍历文档树 和 搜索文档树 中有详细解释.现在介绍一下tag中最重要的属性: name和attributes
Name
每个tag都有自己的名字,通过 .name 来获取:
tag.name
# u'b'
如果改变了tag的name,那将影响所有通过当前Beautiful Soup对象生成的HTML文档:
tag.name = "blockquote"
tag
# <blockquote class="boldest">Extremely bold</blockquote>
Attributes
一个tag可能有很多个属性. tag 有一个 “class” 的属性,值为 “boldest” . tag的属性的操作方法与字典相同:
tag['class']
# u'boldest'
也可以直接”点”取属性, 比如: .attrs :
tag.attrs
# {u'class': u'boldest'}
tag的属性可以被添加,删除或修改. 再说一次, tag的属性操作方法与字典一样
beautifulsoup使用
下面的一段HTML代码是 爱丽丝梦游仙境的 的一段内容:
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p><p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p><p class="story">...</p>
"""
from bs4 import BeautifulSoupsoup = BeautifulSoup(html_doc,'lxml')#按照标准的缩进格式的结构输出:
print(soup.prettify())
#通过点取属性的方式只能获得当前名字的第一个tag:
>>> soup.title
<title>The Dormouse's story</title>#通过 string 参数可以搜搜文档中的字符串内容:
>>> soup.title.string
"The Dormouse's story">>> soup.a
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>#find_all( name , attrs , recursive , string , **kwargs )
#find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件.
>>> soup.find_all('a')
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]#找到文档中所有<a>标签和<b>标签:
>>> soup.find_all(["a", "b"])#如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.
>>> soup.find_all(id='link2')
[<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]#find_all() 方法将返回文档中符合条件的所有tag,尽管有时候我们只想得到一个结果.使用 find_all 方法并设置 limit=1 参数不如直接使用 find() 方法.
>>> soup.find(id="link3")
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>>>> soup.find_all("p", "title")
[<p class="title"><b>The Dormouse's story</b></p>]#关键字 class 在Python中是保留字,使用 class 做参数会导致语法错误.bs4.1后改成class_
>>> soup.find(class_='title')
<p class="title"><b>The Dormouse's story</b></p>>>> soup.find_all('p',class_='title')
[<p class="title"><b>The Dormouse's story</b></p>]>>> soup.find_all('p',class_='title')[0]
<p class="title"><b>The Dormouse's story</b></p>>>> soup.find_all('p',class_='title')[0].string
"The Dormouse's story"
3、lxml
lxml的安装相对复杂一点,你可以利用anaconda来安装。
和BeautifulSoup一样,使用lxml的第一步也是将可能不合法的HTML解析为统一格式。
>>> from lxml.html import fromstring ,tostring
>>> broken_html ='<ul class=country> <li> Area </ul>'
>>> tree = fromstring(broken_html)
>>> tostring(tree,pretty_print=True)
b'<ul class="country"> <li> Area </li>\n</ul>\n'
使用控制台
按F12可进入浏览器控制台,可以在里面测试css选择器
xpath 选择器
Xpath是一种将XML文档的层次结构描述为关系的方式。
选择节点的基本规则
nodename(节点名称):表示选择该节点的所有子节点
“/”:表示选择根节点
“//”:表示选择任意位置的某个节点
“@”: 表示选择某个属性
xpath的谓语条件(Predicate)
所谓"谓语条件",就是对路径表达式的附加条件。
所有的条件,都写在方括号"[]"中,表示对节点进行进一步的筛选。
对于下面的xml文档
<?xml version="1.0" encoding="ISO-8859-1"?><bookstore><book><title lang="eng">Harry Potter</title><price>29.99</price></book><book><title lang="eng">Learning XML</title><price>39.95</price></book>
</bookstore>
/bookstore/book[1] :表示选择bookstore的第一个book子元素。/bookstore/book[last()] :表示选择bookstore的最后一个book子元素。/bookstore/book[last()-1] :表示选择bookstore的倒数第二个book子元素。/bookstore/book[position()<3] :表示选择bookstore的前两个book子元素。//title[@lang] :表示选择所有具有lang属性的title节点。//title[@lang='eng'] :表示选择所有lang属性的值等于"eng"的title节点。/bookstore/book[price] :表示选择bookstore的book子元素,且被选中的book元素必须带有price子元素。/bookstore/book[price>35.00] :表示选择bookstore的book子元素,且被选中的book元素的price子元素值必须大于35。/bookstore/book[price>35.00]/title :表示在例14结果集中,选择title子元素。/bookstore/book/price[.>35.00] :表示选择值大于35的"/bookstore/book"的price子元素。
通配符
# "*"表示匹配任何元素节点。# "@*"表示匹配任何属性值。# node()表示匹配任何类型的节点。
抓取结果
python爬取网页并保存在mongodb中是例子,其中代码有详细的注释:
import requests #requests是一个很实用的Python HTTP客户端库,编写爬虫和测试服务器响应数据时经常会用到。
import re #正则表达式(要从网页代码里面提取特定的标签里面的内容)
from lxml import etree
#lxml:python 的HTML/XML的解析器,
#是libxml2和libxslt两个C库的Python化绑定,它的独特之处在于兼顾了这些库的速度和功能完整性
import pymongo # PyMongo 驱动
import time
from multiprocessing import Pool #进程池headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ''AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/78.0.3904.97 Safari/537.36'
}
#定制header,向访问网站提供所使用的浏览器类型及版本、操作系统及版本、浏览器内核、等信息的标识。# MongoDB的连接
myclient = pymongo.MongoClient('localhost', 27017) #mondodb默认端口号是27017
mydb = myclient["webpages"] #创建数据库webpag
dblist = myclient.list_database_names()
if "webpages" in dblist: #检测数据库是否存在print("该数据库存在")
mycol = mydb['gov.publicity5']
'''
创建集合gov.publicity
在 MongoDB 中,数据库只有在内容插入后才会创建,
就是说,数据库创建后要创建集合(数据表)并插入一个文档(记录),数据库才会真正创建。
'''
collist = mydb.list_collection_names()
if "gov.publicity5" in collist: #检测集合是否存在print("该集合存在")def get_link(url): # 获取每一页公示的所有链接res = requests.get(url, headers) #GET请求selector = etree.HTML(res.text) # 利用 etree.HTML 把字符串解析成 HTML文件href = selector.xpath('//ul[@class="list-group"]/li/a/@href') #获取值为list-group的ul元素下li标签下的a所有href属性对应的值,href 属性用于指定超链接目标的 URL#这里即得到每篇公示的url,比如从源码可以看到某个为 href="./201911/t20191114_489608.html#XPath 是一门在 XML/HTML 文档中查找信息的语言。XPath 可用来在 XML /HTML文档中对元素和属性进行遍历。links = [] #空列表for i in href:links.append(re.sub('^.', 'http://pnr.sz.gov.cn/xxgk/gggs', str(i)))'''在上面得到的url前添加http://pnr.sz.gov.cn/xxgk/gggs/这样我们就得到了完整的链接如:http://pnr.sz.gov.cn/xxgk/gggs/201911/t20191114_489608.htmlre.sub()字符串替换函数,第一个参数为正则表达式需要被替换的参数,第二个参数是替换后的字符串,第三个参数为输入的字符串'''return linksdef page_scratch(link): # 抓取公示详细页面信息res = requests.get(link, headers) #GET请求res.encoding = res.apparent_encoding # 更改可能的编码方式也可以直接用"GB2312"selector = etree.HTML(res.text) # 利用 etree.HTML 把字符串解析成 HTML 文件# 公示标题title = selector.xpath('//div[@class="xxym"]/h4/text()')[0] #寻找名为xxym的块级元素下的h4文本# 公示来源source = re.findall('来源:(.*)\n', selector.xpath('//div[@class="xxym"]/h5/text()')[0])[0]# 公示日期# findall 方法能够以列表的形式返回能匹配的子串,语法findall(pattern, string, flags=0)date = re.findall(' (.*?)\t', selector.xpath('//div[@class="xxym"]/h5/text()')[1])[0]# 公示内容article = '\n'.join(selector.xpath('//div[@class="TRS_Editor"]/p/text()'))# 附件的下载连接download_link = selector.xpath('//i[@class="fa fa-caret-right"]/a/@href')if len(download_link) == 0:appendix = '无' #如果没有附件else:appendix = re.search('^http(.*)/', res.url)[0] + download_link[0].replace('./', '') #得到完整的附件链接# 保存到MongoDB中mycol.insert_one({'标题': title, '来源': source, '日期': date, '公示内容': article, '附件链接': appendix})#insert_one() 方法返回 InsertOneResult 对象,该对象包含 inserted_id 属性,它是插入文档的 id 值time.sleep(0.1)# 缓冲,推迟调用线程的运行,单位:秒if __name__ == '__main__': #_name_:当前模块名。try: #如果模块是被直接运行的,则代码块被运行,如果模块是被导入的,则代码块不被运行。urls = ['http://pnr.sz.gov.cn/xxgk/gggs/index.html'] #用一个列表存储页面链接,第一个链接为首页urls.extend(['http://pnr.sz.gov.cn/xxgk/gggs/index_{}.html'.format(i) for i in range(1, 34)]) # 查看1-8页的公示,加上首页共9页#格式化字符串的函数 str.format(),作用是将{}用format()里的内容替换links = [] #空列表,用于存储公示链接for url in urls:links.extend(get_link(url)) #获取每一篇公示的链接pool = Pool(processes=4) #维持执行的进程总数为processespool.map(page_scratch, links)'''map()函数会将第二个参数的需要迭代的列表元素一个个的传入第一个参数我们的函数中,创建一个个进程,放进进程池中第一个参数是我们需要引用的函数多进程,这样主要用于加快爬虫效率'''except: #捕获所有异常print ("error")
总结
通常情况下,lxml是更好的选择,因为该方法快速又健壮,而正则表达式或者beautifulsoup或是速度不快,或是修改不易。
参考
https://www.runoob.com/xml/xml-intro.html(感谢友好的菜鸟教程——xml)
https://www.runoob.com/python3/python3-xml-processing.html(python3——xml、json)
https://github.com/Kr1s77/Python-crawler-tutorial-starts-from-zero/blob/master
https://beautifulsoup.readthedocs.io/zh_CN/latest/(简单但功能不简单的beautifulsoup)
用python进行网络爬虫(三)—— 数据抓取相关推荐
- 22.网络爬虫—APP数据抓取详讲
网络爬虫-APP数据抓取详讲 Fiddler 工作原理 安装完成Fiddler后的配置 前提条件 工具配置 手机数据抓取 Fiddler手机端配置 手机端操作 实战演示 后记 前言:
- python实现scrapy爬虫每天定时抓取数据
python实现scrapy爬虫每天定时抓取数据 1. 前言. 1.1. 需求背景. 每天抓取的是同一份商品的数据,用来做趋势分析. 要求每天都需要抓一份,也仅限抓取一份数据. 但是整个爬取数据的过程 ...
- 基于Python猫眼票房TOP100电影数据抓取
基于Python猫眼票房TOP100电影数据抓取 使用requests库抓取数据 BeatifulSoup解析URL,将数据存入csv文件 处理数据,生成图表 本次爬取数据使用Python语言在jup ...
- python网络爬虫——使用selenium抓取东方财富网上市公司公告
每日公告数量@TOC 一.数据获取与预处理 本文从东方财富网上市公司公告页面获取沪深A股1991-2019年公告数据,按照数据获取的先后顺序,将数据分为以下两个部分一是上市公司公告信息,包括:序号(i ...
- python淘宝爬虫基于requests抓取淘宝商品数据_python淘宝爬虫基于requests抓取淘宝商品数据...
在学校蹭过python的课,觉得python异常强大,趁寒假有时间,瞎搞一下,希望能和大伙一起探讨学习.废话不多说了,直接正题. requests 是Python的http库,可以完成绝大部分与htt ...
- python淘宝爬虫基于requests抓取淘宝商品数据
在学校蹭过python的课,觉得python异常强大,趁寒假有时间,瞎搞一下,希望能和大伙一起探讨学习.废话不多说了,直接正题. requests 是Python的http库,可以完成绝大部分与htt ...
- python table数据抓取_Python爬虫:数据抓取工具及类库详解
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: ncepu_Chen PS:如有需要Python学习资料的小伙伴可以 ...
- java爬虫实现数据抓取
这篇博客我们将用java来实现基本的爬虫数据抓取操作,基本思路就是通过java访问url,然后拿到返回的html文档,并用jsoup解析. 首先我们来看下需要抓取的页面,以我自己的csdn博客列表页面 ...
- Python爬虫三:抓取链家已成交二手房信息(58W数据)
环境:Windows7+python3.6+Pycharm2017 目标:抓取链家北京地区已成交二手房信息(无需登录),如下图,户型.朝向.成交时间价格等,保存到csv.最后一共抓取约58W数据,程序 ...
- 网络爬虫中Fiddler抓取PC端网页数据包与手机端APP数据包
1 引言 在编写网络爬虫时,第一步(也是极为关键一步)就是对网络的请求(request)和回复(response)进行分析,寻找其中的规律,然后才能通过网络爬虫进行模拟.浏览器大多也自带有调试工具可以 ...
最新文章
- 个人计算机用户隐私保护全接触(2)
- 吴恩达 coursera ML 第十二课总结+作业答案
- python异步和多线程_Python 异步 IO(asyncio)、多进程、多线程性能对比
- 《学习R》笔记:科学计算器、检查变量和工作区、向量、矩阵和数组、列表和数据框...
- twisted系列教程八–延迟的诗
- Codeforces Round #205 (Div. 2) : D
- 界面设计--北京创享数码的设计案例(很不错的看看吧)
- rust腐蚀怎么单人游戏_腐蚀RUST怎么提高帧数_腐蚀RUST提高FPS方法_52pk单机游戏
- javaCV开发详解之7:让音频转换更加简单,实现通用音频编码格式转换、重采样等音频参数的转换功能(以pcm16le编码的wav转mp3为例)...
- 5.程序员的自我修养---Windows PE/COFF
- DBeaver数据库连接工具的简单操作
- 转:嵌入式的经典书籍
- 《机器学习实战:基于Scikit-Learn、Keras和TensorFlow第2版》-学习笔记(9):无监督学习技术
- Mac PHP7.4安装
- 配置zabbix管理账号
- okHttp使用中报Could not find method java.nio.file.Files.newOutputStreamo警告问题
- 新路程------imx6 wtd摘要
- java判断是否已数字结尾,正则表达式测试字符串是否以数字结尾
- 神通数据库OSCAR安装
- 有趣的游戏,Java版斗地主游戏实现
热门文章
- springboot 配置日志文件
- Android 关于图片的压缩
- java计算机毕业设计共享充电宝管理系统MyBatis+系统+LW文档+源码+调试部署
- IPSec:IKEv2协议详解
- JVM(3)-垃圾收集机制
- 【数学与算法】最小生成树Spanning Trees
- Viruses!!!!!
- Real-Time Rendering——9.9.4 Rough-Surface Subsurface Models粗糙表面地下模型
- [转载]MIT人工智能实验室:如何做研究
- 腾讯计算机安全实验室,TRP-AI反病毒引擎创新:腾讯安全最新成果入围顶级学术会议...