发送http请求 以csdn为例,鼠标右键点击检查(或F12进入开发者模式),然后点击Network,刷新网页,继续点击Name列表中的第一个。我们发现此网站的请求方式为GET,请求头Headers反映用户电脑系统、浏览器版本等信息。
在展开框中选择请求标头,一般拿到Cookie和User-Agent就可以(前者用来加载登陆状态,后者用来伪装浏览器访问)。
构造一个请求
1 2 3 4 5 6 url = 'https://blog.csdn.net/xxx/.html' header = { "User-Agent": "Mozilla/5.0 (xxx)", "Cookie": "uuid_tt_dd=xxxxx" } response = requests.get(url, headers=header, verify=False, timeout=10)
verify设为False可以规避认证问题,同样也存在风险(有可能被第三方攻击)。真正的勇士从不在意这些。
作为进阶,你还可以随机设一些user-agent列表来模拟不同浏览器访问。
解析网页内容 有很多方式,这里使用 BeautifulSoup(TODO: 不同解析库的异同、哪个是如今最流行的)
1 2 3 4 soup = BeautifulSoup(response.content, 'html.parser') print(soup.prettify()) # 输出页面内容,帮助你理解页面结构 # 提取文章链接 article_list = soup.find('ul', class_='column_article_list')
基本上,soup.find能解决百分之90的问题,核心在于你要先找到自己想爬取的内容在哪里。 一种方式是,在你想要爬取的内容上右击,选择检查,会自动引到对应的源代码。
图片区域
以上是通过右击找到了csdn首页的推荐文章列表,如果想要爬取首页这一列所有的推荐文章链接,可以看到,它们都属于<div class="Community">这个大类。那么你可以:
1 article_list = soup.find('div' , class_='Community' )
实际内容往往层层嵌套,拿到所有小类并不是终极:
图片区域
上图红框里的a中的href字段才是你想要的链接。那么你需要找到所有小类列表中的<div class="content">,再找到a,再去获取a中的href:
1 2 3 4 5 6 7 8 9 10 11 if not article_list: print("No article list found.") else: article_links = [] article_items = article_list.find_all('div', class_='content') for item in article_items: a_tag = item.find('a') if a_tag and 'href' in a_tag.attrs: link = a_tag['href'] article_links.append(link)
这样就拿到了。后面可以再读取文章内容、标题,然后保存为md什么的,原理是一样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 from markdownify import markdownify as mdfor link in article_links: article_response = requests.get(link, headers=header, verify=False , timeout=10 ) article_soup = BeautifulSoup(article_response.content, 'html.parser' ) article_content = article_soup.find('div' , id ='content_views' ) if article_content: markdown_content = md(str (article_content)) title = article_soup.find('h1' , class_='title-article' ).text.strip().replace(" " , "" ).replace("/" , "-" ) filename = f"{output_dir} /{title} .md" with open (filename, 'w' , encoding='utf-8' ) as f: f.write(markdown_content) print (f"Saved {filename} " ) else : print (f"No content found for {link} " ) wait_time = random.uniform(1 , 10 ) time.sleep(wait_time) print ("All articles have been processed." )
一些需要注意的小tips:
random.uniform: 随机生成一个在[x,y]范围内的实数