爬虫的一些案例
相信大家使用爬虫时,都是一股脑跑进网上查询别人的代码。然后照搬网上的,发现运行的时候并没有很好地符合自己的预期。
现在我来给大家指出爬虫的基本流程,如果有错误,还望大家指正。
爬虫流程:
- 首先先分析需要爬取的网站,有些网站是有robot.txt,不允许哪些爬取,允许爬取哪些内容,爬取一个网站首先得注意一下这个内容,保证自己爬取的行为不会对别人的网站造成不可避免的伤害。
- 然后应该分析自己要爬取的内容,分析基本流程。有些网站刚进入时他的主页时,会要求你登录,不然不会给进入和爬取。
- 制定一个爬取的流程,例如一个url (网站的初始页面),大多数是可以直接通过url进入的,但是有些网站会通过检查你的cookie来判断你有没有登录,会强制你到登录页面。
- 如何得到你想要爬取的url,首先你应该进入到该网站,使用浏览器的网络分析工具,鼠标右键点击检查或者键盘上的F12,这样就可以分析所要爬取的页面了。
现在来列举一些python使用的包。
- 用于请求网页的python自带的urllib,requests
- 用于分析网页页面的BeautifulSoup,lxml(复杂操作推荐lxml)
- 爬取和下载可以直接使用python的open函数,对于文本或者视频不过是是否选取二进制写人模式
- 还有一些模仿浏览器登录的selenium,对于一些动态页面的爬取比较有效。
现在列出我写的一个爬取实例:
这份代码能1到的事情:
- 反鉴别,因为你的header默认是一个python爬虫的,一些网站看到这样的表头直接忽略,并且过多的请求,也会临时封禁你的ip地址,代码中会在每次请求访问一个页面,会换一个表头,无法让对方鉴别出来。
- 保持像个人样,不要请求过快,代码中的一些时间设置是为了更好模仿人的行为
- 如果爬取过多,需要你跟网站保持一个会话状态,使用requests中的session很好的与网站保持,因为你每次使用get,而没有保持会话,这样get再次使用的ip地址,而这个ip地址持续地浪费服务器的资源,肯定会把这个ip地址封禁的,如果你使用的ip被封禁了,只要断开你连的wifi(例如局域网这种),会重新分配一个ip地址给你。
- 使用selenium模仿浏览器,因为我要爬取的网站有javascript动态显示,所以获取它的索引会比较麻烦一点,使用selenium模仿谷歌浏览器登录,然后爬取其中的url.
python
import requests
from lxml import etree
import random
import time
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
max_entries = 3
user_agent_list = [
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/61.0",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
"Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36"
]
headers = {"User-Agent": random.choice(user_agent_list),
"Accept-Language":"zh-CN,zh;q=0.9,zh-TW;q=0.8,zh-HK;q=0.7,en-US;",
"Accept-Encoding":"gzip,deflate,br,zstd"
}
parser =etree.HTMLParser(encoding="utf-8")
session = requests.Session()
options = webdriver.ChromeOptions()
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(10)
def get_novel_list(url):
global driver
novel_chapters = {}
try:
driver.get(url)
except requests.exceptions.ConnectionError as e:
print("Connect aborted")
nameElems = driver.find_elements(By.XPATH,'//div[@class="direList font14 chapter_list"]/ul/li/div[@class="name"]/a')
for nameElem in nameElems:
name = nameElem.text
href = nameElem.get_attribute("href")
if name and href:
novel_chapters[name]=href
nextPage = driver.find_element(By.CLASS_NAME,'next')
nextPage.click()
time.sleep(5)
nameElems = driver.find_elements(By.XPATH,'//div[@class="direList font14 chapter_list"]/ul/li/div[@class="name"]/a')
for nameElem in nameElems:
name = nameElem.text
href = nameElem.get_attribute("href")
if name and href:
novel_chapters[name]=href
driver.quit()
return novel_chapters
def get_novel_content(novelList):
global baseUrl
global headers
global parser
global dirs
global max_entries
novelListChapter = {}
for name, url in novelList.items():
novelListChapter[name] = []
print(f'Downloading {name}:{url}......')
novelListChapter[name].append(url)
try:
headers["User-Agent"]= random.choice(user_agent_list)
html = session.get(url,headers=headers,timeout=60)
time.sleep(random.uniform(3,12))
except requests.exceptions.ConnectionError as e:
print("Connection aborted")
tree = etree.HTML(html.content,parser=parser)
chapterName = dirs+"/"+name+".txt"
with open(chapterName,"w") as f:
while True:
texts = tree.xpath('//div[@class="content font18"]/p/text()')
for text in texts:
f.write(text+'\n')
NextUrl = tree.xpath('//div[@class="btnW font14"]/a[last()]/@href')[0]
absoluteUrl = baseUrl + NextUrl
if(url[:12] != NextUrl[:12]):
break
for i in range(max_entries):
try:
headers["User-Agent"]= random.choice(user_agent_list)
html = session.get(absoluteUrl,headers=headers,timeout=60)
time.sleep(random.uniform(3,12))
except requests.exceptions.ConnectionError as e:
print("Connection aborted")
else:
tree = etree.HTML(html.content,parser=parser)
break
if __name__ == "__main__":
baseUrl = "https://www.qianbixiaoshuo.com"
novelUrl = "/book/0D4D.html"
dirs = "狂神小说"
if not os.path.exists(dirs):
os.makedirs(dirs)
Url = baseUrl + novelUrl
NovelList = get_novel_list(Url)
get_novel_content(NovelList)