Python 爬虫爬取微信文章

发布时间:2019-08-27 08:02:02编辑:auto阅读(2087)

     爬取公众号文章

    搜狗微信平台为入口 地址:http://weixin.sogou.com/

    --------------------------------------------------------------

    搜索关键词“科技”对比网址变化情况

    查看网址http://weixin.sogou.com/weixin?type=2&query=%E7%A7%91%E6%8A%80&ie=utf8&s_from=input&_sug_=y&_sug_type_=&w=01019900&sut=1942&sst0=1528078622302&lkt=1%2C1528078622200%2C1528078622200

    查看下一页的网址http://weixin.sogou.com/weixin?query=%E7%A7%91%E6%8A%80&_sug_type_=&sut=1942&lkt=1%2C1528078622200%2C1528078622200&s_from=input&_sug_=y&type=2&sst0=1528078622302&page=2&ie=utf8&w=01019900&dr=1

    查看第三页网址http://weixin.sogou.com/weixin?query=%E7%A7%91%E6%8A%80&_sug_type_=&sut=1942&lkt=1%2C1528078622200%2C1528078622200&s_from=input&_sug_=y&type=2&sst0=1528078622302&page=3&ie=utf8&w=01019900&dr=1

    -------------------------------------------------------------

    对比上面网址 看到type=2,page=页码,quary=关键词

    http://weixin.sogou.com/weixin?type=2&quary=关键词&page=页码

    测试http://weixin.sogou.com/weixin?type=2&quary=科技&page=2 访问正常与上面第二个页面网址打开的内容一致,也就是说简化的网址能正常访问


    接着查看页面源代码,分析里面的文章链接,并测试链接是否为正是链接(链接编码是否一致)

    <a data-z="art" target="_blank" id="sogou_vr_11002601_img_0" href="http://mp.weixin.qq.com/s?src=11&timestamp=1528081388&ver=917&signature=qZMxpmvj4qn3CzMqGDpjC*GUmFni2E5rsy7kzRZmWSePCsFB5-EgQ4cZHzLaWrpHrtnz75U9mp85NkOS4VSzZwv-e8FZAGS1SoifHUdKstjiW7REiiv3ZKdk*-Q8xBZu&new=1" uigs="article_image_0"><i></i><img src="http://img01.sogoucdn.com/net/a/04/link?appid=100520033&url=http://mmbiz.qpic.cn/mmbiz_jpg/qV0mcHxAh1C5y2oDjZElicU9upoxrMsoBb8uzDspe62fMibIggVIUCLfwep8gc6IDCUuiab1XdmgiajxxtmMwrHOYg/0?wx_fmt=jpeg" onload="resizeImage(this,140,105)" onerror="errorImage(this)"></a>

    构造提取规则pat='<a data-z="art".*?(http://.*?)"'

    根据规则提取到的链接为:

    http://mp.weixin.qq.com/s?src=11&timestamp=1528081388&ver=917&signature=qZMxpmvj4qn3CzMqGDpjC*GUmFni2E5rsy7kzRZmWSePCsFB5-EgQ4cZHzLaWrpHrtnz75U9mp85NkOS4VSzZwv-e8FZAGS1SoifHUdKstjiW7REiiv3ZKdk*-Q8xBZu&new=1

    用浏览器打开此连接错误,说明提取的链接不能直接打开,链接内容与真实链接有差异,

    image.png

    用前面的页面上直接点开文章,查看真实链接

    https://mp.weixin.qq.com/s?src=11&timestamp=1528081388&ver=917&signature=qZMxpmvj4qn3CzMqGDpjC*GUmFni2E5rsy7kzRZmWSePCsFB5-EgQ4cZHzLaWrpHrtnz75U9mp85NkOS4VSzZwv-e8FZAGS1SoifHUdKstjiW7REiiv3ZKdk*-Q8xBZu&new=1

    对比发现两个链接的差异在于有没有“amp;”,所以去掉这个就可以得到真实链接

    可以用url.replace("amp;","")去掉对应的多余字符


    在文章页面中需要提取标题和文本内容

    经过页面源码分析 用下面规则提取相应内容

    titlepat='var msg_title = "(.*?)";'

    contentpat='id="js_content">(.*?)id="js_sg_bar"'


    下面上代码,代码中的IP代理是注释掉的,用免费IP代理很难成功,大多数地址不能正常使用,为了防止微信屏蔽本机地址,所以,加入处理时间等待time.sleep()。

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import re
    import urllib.request
    import time
    import urllib.error
    
    ##模拟浏览器安装headers
    headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36")
    opener=urllib.request.build_opener()
    opener.addheaders=[headers]
    urllib.request.install_opener(opener)
    ##设置列表用于存储链接
    listurl=[]
    
    ##定义代理服务器函数
    #def use_proxy(proxy_addr,url):
    #	try:
    #		import urllib.request
    #		proxy=urllib.request.ProxyHandler({'http':proxy_addr})
    #		opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
    #		urllib.request.install_opener(opener)
    #		data=urllib.request.urlopen(url).read().decode('utf-8')
    #		data=str(data)
    #		return data
    #	except urllib.error.URLError as e:
    #		if hasattr(e,"code"):
    #			print(e.code)
    #		if hasattr(e,"reason"):
    #			print(e.reason)
    #		time.sleep(10)
    #	except Exception as e:
    #		print("exception"+str(e))
    #		time.sleep(1)
    		
    ##定义获取页面所有文章链接
    def getlisturl(key,pagestart,pageend):
    	try:
    		page=pagestart
    		keycode=urllib.request.quote(key)
    #		pagecode=urllib.request.quote("&page")
    		for page in range(pagestart,pageend+1):
    			url="http://weixin.sogou.com/weixin?type=2&query="+keycode+"&page="+str(page)
    			data1=urllib.request.urlopen(url).read().decode('utf-8')
    			data1=str(data1)
    			listurlpat='<a data-z="art".*?(http://.*?)"'
    			listurl.append(re.compile(listurlpat,re.S).findall(data1))
    			time.sleep(2)
    		print("共获取到"+str(len(listurl))+"页")
    		print("第2页链接数"+str(len(listurl[1]))+"个")
    		return listurl
    	except urllib.error.URLError as e:
    		if hasattr(e,"code"):
    			print(e.code)
    		if hasattr(e,"reason"):
    			print(e.reason)
    		time.sleep(10)
    	except Exception as e:
    		print("exception"+str(e))
    		time.sleep(1)
    
    ##定义获取文章内容
    def getcontent(listurl):
    	i = 0
    	#设置本地文件中的开始html编码
    	html1 = '''
    			<!DOCTYPE html>
    			<html>
    			<head>
    			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    			<title>微信文章页面</title>
    			</head>
    			<body>
    			'''
    	fh=open("/home/urllib/test/1.html","wb")
    	fh.write(html1.encode("utf-8"))
    	fh.close()
    	#再次以追加写入的方式打开文件,以写入对应文章内容
    	fh=open("/home/urllib/test/1.html","ab")
    	for i in range(0,len(listurl)):
    		for j in range(0,len(listurl[i])):
    			try:
    				url=listurl[i][j]
    				url=url.replace("amp;","")
    				data=urllib.request.urlopen(url).read().decode('utf-8')
    				data=str(data)
    				titlepat='var msg_title = "(.*?)";'
    				contentpat='id="js_content">(.*?)id="js_sg_bar"'
    				title=re.compile(titlepat).findall(data)
    				content=re.compile(contentpat,re.S).findall(data)
    				#初始化标题与内容
    				thistitle = "此次没有获取到"
    				thiscontent= "此次没有获取到"
    				#如果标题列表不为空,说明找到了标题,取列表第0个元素,即此次标题赋给变量thistitle
    				if (title!=[]):
    					thistitle = title[0]
    				if (content!=[]):
    					thiscontent = content[0]
    				#将标题与内容汇总赋给变量dataall
    				dataall = "<p>标题为:"+thistitle+"</p><p>内容为:"+thiscontent+"</p><br>"
    				fh.write(dataall.encode('utf-8'))
    				print("第"+str(i)+"个网页第"+str(j)+"次处理")
    				time.sleep(1)
    			except urllib.error.URLError as e:
    				if hasattr(e,"code"):
    					print(e.code)
    				if hasattr(e,"reason"):
    					print(e.reason)
    				time.sleep(10)
    			except Exception as e:
    				print("exception"+str(e))
    				time.sleep(1)	
    				
    	fh.close()
    	html2='''</body>
    	</html>
    	'''
    	fh=open("/home/urllib/test/1.html","ab")
    	fh.write(html2.encode("utf-8"))
    	fh.close()
    key="科技"
    #proxy="122.114.31.177:808"
    pagestart=1
    pageend=3
    listurl=getlisturl(key,pagestart,pageend)
    getcontent(listurl)

    执行结果正常:

    image.png

    生成1.html  用浏览器打开,可以看到没提取的多篇文章内容

    image.png

    现在代码可以直接使用的(2018-06-03)

    随着时间推移,由于页面源码常会出现变化,正则匹配常常需要自行分析,参考上面代码,调整正则表达式,即可提取内容





关键字