文章自动采集(腾讯新闻主页上所有新闻爬取分解目标一步地做 )
优采云 发布时间: 2021-08-29 00:05文章自动采集(腾讯新闻主页上所有新闻爬取分解目标一步地做
)
昨天我用python写了一个天气预报采集,今天我在激动的同时写了一个新闻采集。
目标是抓取腾讯新闻首页的所有新闻,获取每条新闻的名称、时间、来源和正文。
接下来分解目标,一步一步来。
第一步:抓取首页的所有链接,写入文件。
按照上一篇文章的方法,可以轻松获取整个首页的文字内容。
我们都知道html链接的标签是“a”,链接的属性是“href”,即获取html中所有的tag=a,attrs=href值。
查了资料,一开始打算用HTMLParser,写出来了。但是它有一个问题,就是不能处理汉字。
1 class parser(HTMLParser.HTMLParser):
2 def handle_starttag(self, tag, attrs):
3 if tag == 'a':
4 for attr, value in attrs:
5 if attr == 'href':
6 print value
后来用了SGMLParser,就没有这个问题了。
1 class URLParser(SGMLParser):
2 def reset(self):
3 SGMLParser.reset(self)
4 self.urls = []
5
6 def start_a(self,attrs):
7 href = [v for k,v in attrs if k=='href']
8 if href:
9 self.urls.extend(href)
SGMLParser 需要为某个标签重新加载它的函数,这里是把所有的链接放到这个类的urls中。
1 lParser = URLParser()#分析器来的
2 socket = urllib.urlopen("http://news.qq.com/")#打开这个网页
3
4 fout = file('urls.txt', 'w')#要把链接写到这个文件里
5 lParser.feed(socket.read())#分析啦
6
7 reg = 'http://news.qq.com/a/.*'#这个是用来匹配符合条件的链接,使用正则表达式匹配
8 pattern = re.compile(reg)
9
10 for url in lParser.urls:#链接都存在urls里
11 if pattern.match(url):
12 fout.write(url+'\n')
13
14 fout.close()
这样,所有符合条件的链接都保存在 urls.txt 文件中。
第 2 步:对于每个链接,获取其网页内容。
很简单,打开urls.txt文件,一行一行读取即可。
这里可能看起来没有必要,但是基于我强烈的解耦愿望,我还是果断地写在了文件中。如果以后使用面向对象编程,重构起来非常方便。
获取网页内容比较简单,但是需要将网页内容保存在一个文件夹中。
这里有几个新用法:
1 os.getcwd()#获得当前文件夹路径
2 os.path.sep#当前系统路径分隔符(是这个叫法吗?)windows下是“\”,linux下是“/”
3
4 #判断文件夹是否存在,如果不存在则新建一个文件夹
5 if os.path.exists('newsdir') == False:
6 os.makedirs('newsdir')
7
8 #str()用来将某个数字转为字符串
9 i = 5
10 str(i)
通过这些方法,将字符串保存到某个文件夹中的不同文件不再是一项艰巨的任务。
第三步:枚举每个网页,根据正则匹配获取目标数据。
以下方法用于遍历文件夹。
1 #这个是用来遍历某个文件夹的
2 for parent, dirnames, filenames in os.walk(dir):
3 for dirname in dirnames
4 print parent, dirname
5 for filename in filenames:
6 print parent, filename
遍历,读取,匹配,结果出来了。
我用来提取数据的正则表达式是这样的:
reg = '.*?(.*?).*?(.*?).*?<a .*?>(.*?)</a>.*?(.*?)'
其实这个和上的新闻并不匹配,因为上面的新闻有两种格式,标签也有点不同,所以只能提取一种。
还有一点是,通过正则表达式提取绝对不是主流的提取方式。如果需要采集other网站,就需要改正则表达式,比较麻烦。
提取后观察发现正文部分总是混入一些不相关的信息,如“”“”等。所以我通过正则表达式切身体。
1 def func(str):#谁起的这个名字
2 strs = re.split(".*?|.*?|&#[0-9]+;||", str)#各种匹配,通过“|”分隔
3 ans = ''
4 #将切分的结果组合起来
5 for each in strs:
6 ans += each
7 return ans
这样基本上可以提取腾讯网站上的所有文字。
到此,整个采集就结束了。
显示我提取的结果(没有自动换行,隐藏在右侧):
注意:
1、 打开某个网址时,如果网址是坏的(打不开),不处理会报错。我只是简单的使用了处理异常的方法,估计应该还有其他方法。
try:
socket = urllib.urlopen(url)
except:
continue
2、Python “.”登录正则表达式可以匹配任何字符,除了“\n”。
3、如何去掉字符串末尾的“\n”? Python的处理优雅到死!
1 if line[-1] == '\n':
2 line = line[0:-1]