最近学完 Python, 写了几个爬虫练练手, 网上的教程有很多, 但是有的已经不能爬了, 主要是网站经常改, 可是爬虫还是有通用的思路的, 即下载数据, 解析数据, 保存数据. 下面一一来讲.
1. 下载数据
首先打开要爬的网站, 分析 URL, 每打开一个网页看 URL 有什么变化, 有可能带上上个网页的某个数据, 例如 xxID 之类, 那么我们就需要在上一个页面分析 html, 找到对应的数据. 如果网页源码找不到, 可能是 ajax 异步加载, 去 xhr 里去找.
有的网站做了反爬的处理, 可以添加 User-Agent : 判断浏览器
- self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
- # 初始化 headers
- self.headers = {'User-Agent': self.user_agent}
如果不行, 在 Chrome 上按 F12 分析请求头, 请求体, 看需不需要添加别的信息, 例如有的网址添加了 referer: 记住当前网页的来源, 那么我们在请求的时候就可以带上.
下载数据的模块有 urllib,urllib2 及 Requests
Requests 相比其他俩个的话, 支持 HTTP 连接保持和连接池, 支持使用 cookie 保持会话, 支持文件上传, 支持自 动确定响应内容的编码, 支持国际化的 URL 和 POST 数据自动编码, 而且 api 相对来说也简单, 但是 requests 直接使用不能异步调用, 速度慢.
html = requests.get(url, headers=headers) #没错, 就是这么简单
urllib2 以我爬取淘女郎的例子来说明:
- user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
- headers = {'User-Agent': user_agent}
- # 注意: form data 请求参数
- params = 'q&viewFlag=A&sortType=default&searchStyle=&searchRegion=city:&searchFansNum=¤tPage=1&pageSize=100'
- def getHome():
- url = 'https://mm.taobao.com/tstar/search/tstar_model.do?_input_charset=utf-8'
- req = urllib2.Request(url, headers=headers)
- # decode('utf - 8')解码 把其他编码转换成 unicode 编码
- # encode('gbk') 编码 把 unicode 编码转换成其他编码
- # "gbk".decode('gbk').encode('utf - 8')
- # unicode = 中文
- # gbk = 英文
- # utf - 8 = 日文
- # 英文一> 中文一> 日文, unicode 相当于转化器
- html = urllib2.urlopen(req, data=params).read().decode('gbk').encode('utf-8')
- # json 转对象
- peoples = json.loads(html)
- for i in peoples['data']['searchDOList']:
- #去下一个页面获取数据
- getUseInfo(i['userId'], i['realName'])
2. 解析数据
解析数据也有很多方式, 我只看了 beautifulsoup 和正则, 这个例子是用正则来解析的
- def getUseInfo(userId, realName):
- url = 'https://mm.taobao.com/self/aiShow.htm?userId=' + str(userId)
- req = urllib2.Request(url)
- html = urllib2.urlopen(req).read().decode('gbk').encode('utf-8')
- pattern = re.compile('<img.*?src=(.*?)/>', re.S)
- items = re.findall(pattern, html)
- x = 0
- for item in items:
- if re.match(r'.*(.jpg")$', item.strip()):
- tt = 'http:' + re.split('"', item.strip())[1]
- down_image(tt, x, realName)
- x = x + 1
- print('下载完毕')
正则表达式说明
match: 匹配 string 开头, 成功返回 Match object, 失败返回 None, 只匹配一个.
search: 在 string 中进行搜索, 成功返回 Match object, 失败返回 None, 只匹配一个.
findall: 在 string 中查找所有 匹配成功的组, 即用括号括起来的部分. 返回 list 对象, 每个 list item 是由每个匹配的所有组组成的 list.
1).*? 是一个固定的搭配,. 和 * 代表可以匹配任意无限多个字符, 加上? 表示使用非贪婪模式进行匹配, 也就是我们会尽可能短地做匹配
2)(.*?)代表一个分组, 如果有 5 个 (.*?) 就说明匹配了五个分组
3) 正则表达式中,"." 的作用是匹配除 "\n" 以外的任何字符, 也就是说, 它是在一行中进行匹配. 这里的 "行" 是以 "\n" 进行区分的. HTML 标签每行的末尾有一个 "\n", 不过它不可见. 如果不使用 re.S 参数, 则只在每一行内进行匹配, 如果一行没有, 就换下一行重新开始, 不会跨行. 而使用 re.S 参数以后, 正则表达式会将这个字符串作为一个整体, 将 "\n" 当做一个普通的字符加入到这个字符串中, 在整体中进行匹配.
3. 保存数据
数据解析后可以保存到文件或数据库中, 这个例子是保存到了文件中, 很简单, 就不做说明了, 在下篇讲如何将数据保存到数据库
- def down_image(url, filename, realName):
- req = urllib2.Request(url=url)
- folder = 'e:\\images\\%s' % realName
- if os.path.isdir(folder):
- pass
- else:
- os.makedirs(folder)
- f = folder + '\\%s.jpg' % filename
- if not os.path.isfile(f):
- print f
- binary_data = urllib2.urlopen(req).read()
- with open(f, 'wb') as temp_file:
- temp_file.write(binary_data)
GitHub 地址, 还有其他网站爬虫, 欢迎 star: https://github.com/peiniwan/CreeperTest
来源: https://www.cnblogs.com/liuyu0529/p/9120529.html