一。思路:python 内置了两个网络库 urlib和urlib2,但是这两个库使用起来不是很方便,所以这里使用广受好评的第三库requests。 (基本思路使用requests获取页面信息,使用正则表达式解析页面,为了更加迅速的爬取数据,使用multiprocessing实现多进程抓取。下一篇文章会使用Beautifulsoup来解析页面。这篇文章主要用来记录一下代码过程中遇到的一点问题,关于各个模块的使用自行先熟悉。
环境配置:我用的是Anaconda2 (python 2.7)
二。Requests:
1.request官方文档:http://docs.python-requests.org/en/master/
使用requests的get请求获得猫眼Top100的html。通过状态码来判断请求是否成功,如果请求不成功,那么返回None.用Requests的RequestException来捕捉异常:
def get_one_page(url): try: response=requests.get(url) if response.status_code==200: response=response.text return response else: return None except RequestException: return None
2.用正则表达式来解析这个页面。这里面主要用到 compile()和findall()这两个方法。
使用函数compile(pattern,flag) 进行预编译,把我们想要提取的index,title,actor等信息分别用子组来匹配中。findall()返回的是一个元组组成的列表,当正则表达式有多个子组的时候,元组中的每一个元素都是一个子模式的匹配内容。re.S这个参数是在字符串a中,包含换行符\n,在这种情况下,如果不使用re.S参数,则只在每一行内进行匹配,如果一行没有,就换下一行重新开始。而使用re.S参数以后,正则表达式会将这个字符串作为一个整体,在整体中进行匹配。
def parse_one_page(html):
pattern=re.compile('.*?board-index.*?>(\d+).*?data-src="(.*?)".*?name">'
+'(.*?).*?star">(.*?).*?releasetime">(.*?).*?integer">'
+'(.*?).*?fraction">(\d+).*? ',re.S)
items=re.findall(pattern,html) ## 这个时候items是一个元组组成的列表
for item in items: ##遍历列表,用一个生成器来存储遍历到的结果
yield {
"index":item[0],
"title":item[2],
"actor":item[3].strip()[3:],
"time":item[4].strip()[5:],
"score":item[5]+item[6] ,
"image":item[1]
}
3.把爬取下来的结果存取下来。
这里要用到 json.dumps()函数,需要注意的是json.dumps是将dict转化成str格式,json.loads是将str转化成dict格式.
这儿我用的是with open函数来写的python 3中可以直接给open函数传入(encoding='utf-8')编码参数,但是python 2.7中需要引入codes模块才可以给open函数传入编码参数,否则会报错。
def write_to_file(content):
with open('result.txt','a','utf-8') as f:
#f=codecs.open('result.txt','a','utf-8')
f.write(json.dumps(content,ensure_ascii=False)+'\n')
4.在猫眼Top100榜单看到,每个页面只展示了10个,网页通过一个偏移量offset来设置每个页面展示的上榜电影。
url='http://maoyan.com/board/4?offset='+str(offset)
html=get_one_page(url)
for item in parse_one_page(html):
write_to_file(item)
5. 多线程爬取使用 multiprocessing 这个模块。
5.整个代码块如下:
# -*- coding: utf-8 -*- """ Created on Thu Jun 29 10:23:46 2017 @author: Tana """ import requests import codecs import json from requests.exceptions import RequestException import re import multiprocessing def get_one_page(url): try: response=requests.get(url) if response.status_code==200: response=response.text return response else: return None except RequestException: return None def parse_one_page(html): pattern=re.compile('.*?board-index.*?>(\d+).*?data-src="(.*?)".*?name"> ' +'(.*?).*?star">(.*?).*?releasetime">(.*?).*?integer"> ' +'(.*?).*?fraction">(\d+).*?',re.S) items=re.findall(pattern,html) for item in items: yield { "index":item[0], "title":item[2], "actor":item[3].strip()[3:], "time":item[4].strip()[5:], "score":item[5]+item[6] , "image":item[1] } def write_to_file(content): with codecs.open('result.txt','a','utf-8') as f: # f=codecs.open('result.txt','a','utf-8') f.write(json.dumps(content,ensure_ascii=False)+'\n') f.close() def main(offset): url='http://maoyan.com/board/4?offset='+str(offset) html=get_one_page(url) for item in parse_one_page(html): write_to_file(item) # print html if __name__=='__main__': pool=multiprocessing.Pool() pool.map(main,[i*10 for i in range(10)])