tags:
Python3、爬虫、网页、requests、re、正则表达式
问题描述
浏览网页的时候遇到这篇笔记:
http://www.360doc.com/content/07/0310/18/17841_392130.shtml,
想要把页面上的书籍全下载下来,一共有80多本,手动点击下载太慢,想要快速批量地把下载链接爬取下来,于是用Python写了一个小程序。
爬虫设计
- 先用requests爬取页面内容,
- 再用re抽取书名和下载链接,
- 将结果保存到pandas.DataFrame,
- 最后保存至csv文件
爬取步骤
1、页面抓取
2、正则表达式解析
3、保存到csv文件
4、下载电子书文件
1、页面抓取
requests 是Python3里十分好用的网页爬取解析库,较之内置的urllib2使用起来要方便得多,而且Python3开始已经不支持urllib2了,在这里我使用的是Python 3.5。
Requests is an elegant and simple HTTP library for Python, built for human beings.
一点使用入门:
使用requests解析网页内容十分简单:
- 使用GET方式获取网页:
r = requests.get('https://api.github.com/events')
- 使用POST方式获取网页:
r = requests.post('http://httpbin.org/post', data = {'key':'value'})
在上面两个示例中,我们尝试使用requests获取github上的某些信息,读取网页内容使用:
r.text
返回的HTTPResponse对象r
具有的属性参照下表:
属性名 | 结果 |
---|---|
text | HTTP字符 |
encoding | 响应编码,这个值可以改变,改变之后text属性也会根据编码而变化 |
content | 未编码的二进制数据 |
json() | 返回JSON数据 |
raw | 结果的原始字节流 |
url | 请求的URL |
status_code | 状态码 |
headers | 请求头字典 |
cookies | cookies字典 |
history | 如果发生重定向,所有请求对象都会保存到这里 |
爬取网页内容
我们引入requests包,使用上述示例内容解析网页并将内容返回给content
变量
import requests
url = 'http://www.360doc.com/content/07/0310/18/17841_392130.shtml'
content = requests.get(url).text
可以将从content
保存到本地文件:
import os
with open('contentUrl.txt', 'w', encoding = 'utf-8-sig') as txtfile:
txtfile.write(content)
2、正则表达式解析
re
的教程可以从这里进去:Python 正则表达式。
re
是Python内置的正则表达式包,使用re
匹配字符串分两步走:
- 打包正则表达式字符串:使用
re.compile
将一个字符串转化为正则表达式对象。 - 匹配:使用
re.findall
匹配文本,用法:re.findall(pattern, string)
,findall接受两个参数,一个是预期找到的字符串,一个是匹配的全文。
这里我们需要找到书名和对应的下载链接,先构造两个正则化对象,代码如下
import re
content = content.replace('\n', '').replace(' ','')#清除所有换行符和空格
bookPatterns = re.compile(r'(《.*?》.*?)<br>')
urlPatterns = re.compile(r'<ahref="(http://www.swdyj.com.*?\.(exe|rar|zip|RAR|chm))"')
bookPatterns是书名的正则化对象,urlPatterns是下载链接的正则化对象。
接下来我们需要对网页文本进行匹配。
bookResult = re.findall(bookPatterns, contents)
bookName = bookResult[1:]
urls = [url[0] for url in re.findall(urlPatterns, contents)]
这里的bookName取返回结果index为1开始的数组是因为匹配的文本第一项(index为0)并不是我们想要的结果。
urls是对匹配结果处理过后得到的正确url,不处理的匹配结果:
[('http://www.swdyj.com/sj/GSQSJS.rar', 'rar'),
('http://www.swdyj.com/sj/LZT.rar', 'rar'),
('http://www.swdyj.com/sj/KXZF.rar', 'rar'),
('http://www.swdyj.com/sj/HDCZ.rar', 'rar'),
('http://www.swdyj.com/sj/ZQJYX.rar', 'rar'),
('http://www.swdyj.com/SJ/YDLL.rar', 'rar')]
3、保存到csv文件
这一步我们使用pandas将匹配结果保存到DataFrame对象
import pandas as pd
df = pd.DataFrame(columns = ['Book', 'url'])
df['Book'] = bookName
df['url'] = urls
print(df.head())
with open('results.csv', 'w', encoding = 'utf-8-sig') as csvfile:
df.to_csv(csvfile, index = False)
需要注意的是encoding = 'utf-8-sig'
可以保证保存的文件打开后中文不乱码。
保存结果:
4、下载文件
这个时候就可以畅快地使用BT下载了。
完整代码:
import pandas as pd
import os
import re
import requests
url = 'http://www.360doc.com/content/07/0310/18/17841_392130.shtml'
content = requests.get(url).text
# with open('content.txt', 'w', encoding = 'utf-8-sig') as txtfile:
# txtfile.write(content)
# with open('content.txt', 'r', encoding = 'utf-8-sig') as txtfile:
# contents = txtfile.read().replace('\n', '').replace(' ', '')
contents = content.replace('\n', '').replace(' ', '')
bookPatterns = re.compile(r'(《.*?》.*?)<br>')
urlPatterns = re.compile(r'<ahref="(http://www.swdyj.com.*?\.(exe|rar|zip|RAR|chm))"')
bookResult = re.findall(bookPatterns, contents)
bookName = bookResult[1:]
print(re.findall(urlPatterns, contents))
urls = [url[0] for url in re.findall(urlPatterns, contents)]
df = pd.DataFrame(columns = ['Book', 'url'])
df['Book'] = bookName
df['url'] = urls
with open('results.csv', 'w', encoding = 'utf-8-sig') as csvfile:
df.to_csv(csvfile, index = False)
参考链接:
Requests官方文档:http://docs.python-requests.org/en/master/
Python HTTP库requests 介绍-简书://www.greatytc.com/p/84ea562f0932