使用python抓取搜狗引擎公众号文章

初学python,以写一个爬虫程序入手,记录一下学习过程。

参考:http://www.cnblogs.com/haq5201314/p/9215569.html

还有些内容忘了从哪里参考的了。

首先搭建python运行环境python3.7.0,安装集成开发环境pycharm,具体过程忘了。

由于程序是模拟谷歌浏览器运行,需要下载chromedriver.exe,下载成功后放到项目根目录

下面开始正式编写。

首先,写个数据库链接类,我用的是SQLSERVER2008R2,dbhelper.py文件需要导入pymssql。

1、查询语句执行方法

def ExecQuery(self,sql):
    """
    执行查询语句
    返回的是一个包含tuple的list,list的元素是记录行,tuple的元素是每行记录的字段
    """
    cur = self.__GetConnect
    cur.execute(sql)
    resList = cur.fetchall()

    #查询完毕后必须关闭连接
    self.conn.close()
    return resList

2、非查询语句执行方法

def ExecNonQuery(self,sql):

    #执行非查询语句

    cur = self.__GetConnect
    cur.execute(sql)
    self.conn.commit()
    self.conn.close()

操作数据库的类写完了,开始正式抓取数据。

先模拟打开搜狗引擎的搜索微信公众号的页面

url='http://weixin.sogou.com/weixin?type=1&s_from=input&query={}&ie=utf8&_sug_=y&_sug_type_=&w=01015002&oq=jike&ri=0&sourceid=sugg&stj=0%3B0%3B0%3B0&stj2=0&stj0=0&stj1=0&hp=36&hp1=&sut=4432&sst0=1529305369937&lkt=5%2C1529305367635%2C1529305369835'.format(name)
r = requests.get(url=url, headers=headers)
#其中的format(name)中的name是要搜索的公众号名称
rsw = re.findall('src=.*&timestamp=.*&ver=.*&signature=.*', str(r.text))

然后从搜索到接结果中选择第一个打开,进入公众号文章列表页

cis = re.findall('.*?==', str(rsw[0]))
qd = "".join(cis)
qd2 = "{}".format(qd)
qd3 = qd2.replace(';', '&')
urls = 'https://mp.weixin.qq.com/profile?'.strip() + qd3
driver = webdriver.Chrome()
driver.get(urls)

由于列表页的数据都是由js动态加载出来的, 如果按照常规方法取html标签中的内容是取不到值的,这时候需要直接从js脚本里获取数据,这里会用到selenium库,直接在官网下载安装就行了。

r = driver.execute_script("return msgList")

从js里取数据就上面一行代码,不得不说python太强大了……

msgList是公众号文章列表中js变量的名称,有兴趣的可以在列表页查看源代码看一下。

数据已经拿到,下面就是解析并插入到数据库了。

源码:dbhelper.py

 

#coding=utf-8
#!/usr/bin/env python

import pymssql


class MSSQL:

    def __init__(self,host,user,pwd,db):
        self.host = host
        self.user = user
        self.pwd = pwd
        self.db = db

    @property
    def __GetConnect(self):
        if not self.db:
            raise(NameError,"没有设置数据库信息")
        self.conn = pymssql.connect(host=self.host,user=self.user,password=self.pwd,database=self.db,charset="utf8")
        cur = self.conn.cursor()
        if not cur:
            raise(NameError,"连接数据库失败")
        else:
            return cur

    def ExecQuery(self,sql):
        cur = self.__GetConnect
        cur.execute(sql)
        resList = cur.fetchall()

        #查询完毕后必须关闭连接
        self.conn.close()
        return resList

    def ExecNonQuery(self,sql):

        #执行非查询语句

        cur = self.__GetConnect
        cur.execute(sql)
        self.conn.commit()
        self.conn.close()

抓取数据类:

from selenium import webdriver
import requests
import re


class crawhelper:

        def grab(name):
                headers={}
                url='http://weixin.sogou.com/weixin?type=1&s_from=input&query={}&ie=utf8&_sug_=y&_sug_type_=&w=01015002&oq=jike&ri=0&sourceid=sugg&stj=0%3B0%3B0%3B0&stj2=0&stj0=0&stj1=0&hp=36&hp1=&sut=4432&sst0=1529305369937&lkt=5%2C1529305367635%2C1529305369835'.format(name)
                r = requests.get(url=url, headers=headers)
                rsw = re.findall('src=.*&timestamp=.*&ver=.*&signature=.*', str(r.text))
                if '验证码' in str(r.text):
                        print('[-]发现验证码请访问URL:{}后在重新运行此脚本'.format(r.url))
                        exit()
                else:
                        cis = re.findall('.*?==', str(rsw[0]))
                        qd = "".join(cis)
                        qd2 = "{}".format(qd)
                        qd3 = qd2.replace(';', '&')
                        urls = 'https://mp.weixin.qq.com/profile?'.strip() + qd3
                        driver = webdriver.Chrome()
                        driver.get(urls)
                        if '验证码' in str(driver.page_source):
                                print('[-]发现验证码请访问URL:{}后在重新运行此脚本'.format(driver.current_url))
                                exit()
                        else:
                                r = driver.execute_script("return msgList")
                                #print(r)
                                return r

 解析插入数据库类

#!/usr/bin/python
# -*- coding: utf-8 -*-
#从搜狗搜索公众号并抓取数据,保存到数据库(已有数据跳过)
import psp
import dbhelper
#import pymssql
import time
import datetime
#import SlopeTwo
#import numpy as np
#import pandas as pd
#from itertools import groupby
#import  requests
#import  re
from bs4 import BeautifulSoup

from urllib.request import urlopen
#import  sys
#import importlib
#importlib.reload(sys)
#codeint=sys.getdefaultencoding()
import  chardet

#获取公众号素材详细内容
def getContent(url):
    page = urlopen(url)
    html = page.read().decode('utf-8')
    if '验证码' in str(html):
        print('[-]发现验证码请访问URL:{}后在重新运行此脚本'.format(url))
        exit()
    soup=BeautifulSoup(html,"html.parser")
    result = soup.find_all('div',{'class':'rich_media_content'})
    #print (result)
    return result

if __name__=='__main__':
    try:


        ms = dbhelper.MSSQL(host="111.111.222.222",user="sa",pwd="123456",db="Test")
        #获取数据库中介入正常的公众号名称
        name_list=ms.ExecQuery('select id,name from account where status=2')
        for id,name in name_list:
            #获取每个公众号对应的最新10天的数据
            list=psp.crawhelper.grab(name)
            list=list["list"]
            for item in list:
                try:
                    author=item["app_msg_ext_info"]["author"]
                    url="https://mp.weixin.qq.com"+item["app_msg_ext_info"]["content_url"]
                    content=getContent(url.replace('&','&'))
                    content=content[0]
                    content=str(content).replace("'","''")
                    cover=item["app_msg_ext_info"]["cover"]
                    title=item["app_msg_ext_info"]["title"]
                    multi_app_msg_item_list=item["app_msg_ext_info"]["multi_app_msg_item_list"]
                    date_time=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(item["comm_msg_info"]["datetime"]))
                    date_time=str(date_time)[0:-3]
                    index=1
                    create_time=str(datetime.datetime.now())[0:-3]
                    status=1
                    print(name+":"+date_time+":第"+str(index)+"条")
                    result=bytes(content, encoding = "UTF-8")
                    #print (chardet.detect(result))
                    list=ms.ExecQuery("select * from news where title=\'%s\' and account_id=\'%s\'"%(title,id))
                    if(len(list)==0):
                        sql="insert into news(update_time,author,thumb_url,title,url,account_id,index_id,create_time,status,content,public_time) values\
                            (\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\')" %(date_time,author,cover.replace('&','&'),title,url.replace('&','&'),id,index,create_time,status,content,date_time)
                        #print(sql)
                        ms.ExecNonQuery(sql)
                    for model in multi_app_msg_item_list:
                        try:
                            author=model["author"]
                            url="https://mp.weixin.qq.com"+model["content_url"]
                            content=getContent(url.replace('&','&'))
                            content=content[0]
                            content=str(content).replace("'","''")
                            cover=model["cover"]
                            title=model["title"]
                            index=index+1
                            print(name+":"+date_time+":第"+str(index)+"条")
                            result=bytes(content, encoding = "UTF-8")
                            #print (chardet.detect(result))
                            list=ms.ExecQuery("select * from news where title=\'%s\' and account_id=\'%s\'"%(title,id))
                            if(len(list)==0):
                                sql="insert into news(update_time,author,thumb_url,title,url,account_id,index_id,create_time,status,content,public_time) values\
                                (\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\')" %(date_time,author,cover.replace('&','&'),title,url.replace('&','&'),id,index,create_time,status,content,date_time)
                                #print (sql)
                                ms.ExecNonQuery(sql)
                        except Exception as m:
                            print (str(m))
                            continue
                except Exception as n:
                    print (str(n))
                    continue
        print('完成')
    except Exception as e:
        print(str(e))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值