首页 > 编程知识 正文

python爬虫如何爬取,python爬虫爬取实例

时间:2023-05-05 03:43:57 阅读:184253 作者:1013

作者最近在学习python爬虫,在爬取微信文章这个实战项目中遇到了一些小问题,所以写这篇文章来记录一下,顺便分享一下爬取过程。 整体思路 我们选择从搜狗的微信界面(‘https://weixin.sogou.com/’)来获取微信文章的基本信息,由于搜狗有反爬措施,采用代理池,先将搜狗搜索的结果页的源码爬取,之后解析出这一页的文章链接,翻页,继续解析至最后一页,最后访问文章链接获取源码提取所需信息保存到MongoDB中 准备工作 代理池ProxyPool:代理池的作用是用来应对sougo的反爬虫措施,含糊的心情快速翻页时搜狗会跳出验证码识别,这时的网页请求会由200变成302的错误状态,这表示现在的ip被搜狗察觉并且不能再使用它来爬取。
代理池中有许多免费公开的ip,我们从代理池中不断获取ip来保证过程中有可用的ip供我们使用,这里使用的是github上公开的代理池代码附上链接,链接中有使用方法,大家可以自行下载运行:‘https://github.com/Python3WebSpider/ProxyPool’第三方库:除了代理池的requirement.txt中的库,还需要用到re库(正则表达式库)requests库(get网页源码)BeautifulSoup(解析)pymongo(mongodb数据库存取)MongoDB数据库:非必须,可以选择其它的数据库或者文件类型存储 第一步:获取搜索结果界面的源码 由于是静态页面,用requests库就可以很方便的爬取,但需要注意两点:1.搜索中如果不登录vx只能爬取十页的内容 2.需要在出现302的状态码时从代理池中获取新的ip解决第一个问题需要对headers进行设置,这里简单得设置User-Agent和Cookie达到需求解决第二个问题采用从代理池的端口中获取ip附代码及注释: proxy_url = 'http://127.0.0.1:5555/random'#获取代理ip的端口proxy_ip = None#访问用的ip-全局变量base_url ='https://weixin.sogou.com/weixin'headers = { 'Cookie':'自己的cookie', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}keyword = '风景' def get_proxy_ip(): """ 从代理池的端口获取代理ip :return: 代理ip """ try: req = requests.get(proxy_url) if req.status_code == 200: return req.text return None except ConnectionError: return None def get_html(url,ke): """ :param url: 搜狗微信的前缀 :param ke: 搜索的关键词和页数信息 :return: 页面的源码 """ global proxy_ip try: proxy_ip = get_proxy_ip()#获取一个ip proxies = {'http':'http://'+proxy_ip}#使用该ip访问 req = requests.get(url,params=ke,headers = headers,proxies = proxies,allow_redirects = False)#最后一个参数是防止反爬自动跳转页面 if req.status_code == 200: return req.text if req.status_code == 302:#反爬生效,状态码错误 proxy_ip = get_proxy_ip() if proxy_ip: print('use proxy',proxy_ip) return get_html(url,ke)#当代理池的公开ip被占用,此处会循环获取直至有可用ip else: print('get proxy error') return None 第二步:实现翻页,获取每一页的源码 这里只需要改变页数,也就是之前的ke参数即可 def get_index(keyword,page): """ 主要用于定位关键词和页数 :param keyword: 查找关键词 :param page: 页数 :return: """ ke = {'query': f'{keyword}', 'type':'2', 'page':f'{page}'} html = get_html(base_url,ke) return html

通过运行以下代码即可获取100页的源码

def main(): for i in range(1,101): html = get_index(f'{keyword}',i) 第三步:解析尝试获得文章的url 此时我们已经获取了每一页的html变量,现在对每一页的html结构进行分析,找到可能存储着文章url的信息
通过右键检查链接,我们发现每一个文章信息都储存在class为‘news-list’下的< li >中,而链接在< li >的< a >标签的href属性中,点击链接,我们成功跳转到了文章界面

但如果细心的话会发现这个文章界面的url和之前显示的url不同,但显然我不细心,方便区分,称这个是跳转url
但不论怎样,我们都需要将这个url提取出来 def find_url(html): """ 找到文章的跳转url :param html: 搜索页面html :return: 文章的url(跳转)列表 """ arti_url = [] soup = BeautifulSoup(html,"html.parser") ul = soup.find('ul',class_ ='news-list') li_items = ul('li') for i in li_items: a = i.find('a',target='_blank') #print(a.get('href')) arti_url.append(a.get('href')) return arti_url

然后当我进行下一步,获取该url的源码时,我发现不是我想要的界面

第四步:通过re获得真实url 此时我并没有管这个url爬出来的是什么,然后终于发现了两者的url是不同的,显然文章的页面是异步加载出来(好像是这么叫??初学俺也不懂)。而面临这种情况,我脑子里只有分析ajax和用selenium,但我要分析1000页的ajax吗…so我只尝试了selenium,但selenium用谷歌驱动时会直接被搜狗发现是自动化程序,原因好像是有的js文件中包含着驱动文件的名字(经后续其它项目学习中发现有时使用火狐驱动不会被发现)所以这两种方法初步尝试失败这时我注意到了跳转url的源码有一部分长这样
然后我对比了一下跳转后的最终url就是这一串连起来,我高兴了起来
看到这格式整齐的字符串,一串正则表达式就敲了出来: def find_true_url(html): """ 从跳转url中解析出真正的url :param html: :return: """ n_url = '' #part = re.findall(r'+= '.{11}', html) parts = re.findall(r'+= '.+', html) for i in parts: n_url += i[4:-3] n_url.replace("@", "") #print(n_url) return n_url

至此我们得到了文章的真正url

第五步:从真实url获取想要的文章信息

这里只解析了简单的文章名称、公众号名称,解析方法和查找跳转url那里相同,想获取更多的信息也可以自己再加

def parse_arti(html,url): """ :param html: 文章html :param url: 文章真实url :return: 文章中需要提取的信息(字典型) """ soup = BeautifulSoup(html,"html.parser") #print(soup) try:#一定要加try except结构 不然有的链接是视频文章不符合解析规定会卡住 art = { '文章名称': soup.find(id = 'activity-name').string.replace('n','').replace(' ',''), '公众号': soup.find(id = 'js_name').string.replace('n','').replace(' ',''), '链接':url } return art except: return None 第六步:存储到数据库 这里因为是字典类型,所以就存储到了MongoDB,也可以选择不用字典存储然后写入别的文件。这里需要配置一下MongoDB和写一下写入的方法 MONGO_URL = 'localhost'MONGO_DB = 'vx'MONGO_TABLE = 'article'client = pymongo.MongoClient(MONGO_URL)db = client[MONGO_DB]#注意中括号def save_to_mongo(art): try: if db[MONGO_TABLE].insert(art): print('保存成功',art) except Exception: print('存储失败',art) 运行 此时注意,运行前要先运行代理池,不然无法获取代理ip运行代码及数据库截图如下: if __name__ == '__main__': for i in range(1, 101): html = get_index(f'{keyword}', i) arti_url = find_url(html) #print(arti_url) for url in arti_url: html = get_arti_info(url) n_url = find_true_url(html) n_html = get_arti_info(n_url) art = parse_arti(n_html, n_url) save_to_mongo(art)

结语

ok,这就是我的爬虫第一个稍微有点用的实战项目分享,初学爬虫,有些地方表述不清或者不对大家多包涵,希望对你有帮助

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。