天天看点

v2ex的简单爬虫

'''
v2ex的爬虫,只爬首页面,获取贴子的标题和url,再访问帖子url获取主贴内容
长时间频繁执行会被网站封掉
BeautifulSoup4的中文文档 https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
'''

import requests
from bs4 import BeautifulSoup

def get_html(url): #获取页面html函数
    headers= {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0','Referer':'https://movie.douban.com/top250'}
    try:
        html = requests.get(url,headers = headers) #使用get命令访问v2ex的网站
        html.encoding = 'zh-CN' #页面的字符集,可以通过浏览器查看页面源代码来获取
        if html.status_code == 200: #状态http返回状态判断
            print("服务器返回200")
    except Exception as e :
        print("失败服务器返回:%s" % e)
    return html.text #返回html的文本

def get_item(html): #通过html分析获取帖子标题和url的函数
    soup = BeautifulSoup(html,'lxml') #使用BeautifulSoup解析html,能够得到一个 BeautifulSoup 的对象,并能按照标准的缩进格式的结构输出
    #根据帖子标题的样式,比如:<a href="/t/605390#reply2" target="_blank" rel="external nofollow"  class="topic-link">请教大神 MySQL UPDATE 怎么编写包含正则表达式的语句</a>
    #使用soup.find_all命令去匹配a和class="topic-link",获取帖子标题和URL
    topic_title = soup.find_all('a',attrs={'class':'topic-link'}) 
    topic_list = []
    for item in topic_title: #遍历标题对象
        #item.get_text()获取到“请教大神 MySQL UPDATE 怎么编写包含正则表达式的语句”,item['href']获取到"/t/605390#reply2"也就是帖子正文的URL
        temp={'post_title':item.get_text(),'post_url':item['href']}  #组装成dict
        topic_list.append(temp)#把dict组装到list。
    return topic_list #返回帖子标题和URL的list

def get_topic_content(html): #获取帖子正文函数
    soup = BeautifulSoup(html,'lxml') 
    #访问帖子URL获取的HTML,比如:<div class="topic_content">需要处理一个附件记录表,个人想法是增加一个新的字段,将原字段记录处理后写入,最后改程序引用实现<br /><br /> 字段原内容为 /abc/def/ghi/123456789-XXXXXXXX.zzzz<br /><br /> 前段一定是一串数字<br /> - 可能是其它字符 类似 _ 空格等 <br /> XXXXXXXX 可能是 中 /英 文或者其他各种乱七八糟的字符<br /> zzzz 文件扩展名 可能是 3 位 /4 位英文字母<br /><br /> 希望改成 /abc/def/ghi/<a target="_blank" href="http://123456789.xxx" target="_blank" rel="external nofollow"  rel="nofollow">123456789.xxx</a> <br /> 保留路径不变 /abc/def/ghi/<br /> 文件名 截取前面所有数字部分+文件扩展名<br /><br /> 请问该如何编写 UPDATE 语句</div>
    #使用soup.find_all命令去匹配div和class="topic_content",获取帖子正文
    topic_content = soup.find('div',attrs={'class':'topic_content'})
    return topic_content #返回帖子正文

url = "https://www.v2ex.com"
html = get_html(url)
topic_total = get_item(html)

for item in topic_total: #遍历首页帖子汇总的URL访问帖子
    print("="*100)
    print(item['post_title'],url+item['post_url'])
    html = get_html(url+item['post_url']) #调用获取页面html函数
    #print(html)
    post_content = get_topic_content(html) #调用获取帖子正文函数
    print(post_content) #被封后有可能输出None